def _from_dict_value(cls, class_, value, validator): # validate raw input if validator is cls.SOFT_VALIDATION: if issubclass(class_, Unicode) and not isinstance(value, basestring): raise ValidationError(value) if issubclass(class_, Unicode) and not isinstance(value, unicode): # Note that String is a subclass of Unicode if not (issubclass(class_, String) and isinstance(value, str)): value = ProtocolBase.from_string(class_, value) elif issubclass(class_, Decimal) and not isinstance(value, (int, long, float)): raise ValidationError(value) elif issubclass(class_, DateTime) and not ( isinstance(value, unicode) and class_.validate_string(class_, value)): raise ValidationError(value) # get native type if issubclass(class_, ComplexModelBase): retval = cls._doc_to_object(class_, value, validator) elif issubclass(class_, DateTime): retval = ProtocolBase.from_string(class_, value) else: retval = value # validate native type if validator is cls.SOFT_VALIDATION and \ not class_.validate_native(class_, retval): raise ValidationError(retval) return retval
def test_custom_strftime(self): s = ProtocolBase.strftime(datetime.date(1800, 9, 23), "%Y has the same days as 1980 and 2008") if s != "1800 has the same days as 1980 and 2008": raise AssertionError(s) print("Testing all day names from 0001/01/01 until 2000/08/01") # Get the weekdays. Can't hard code them; they could be # localized. days = [] for i in range(1, 10): days.append(datetime.date(2000, 1, i).strftime("%A")) nextday = {} for i in range(8): nextday[days[i]] = days[i + 1] startdate = datetime.date(1, 1, 1) enddate = datetime.date(2000, 8, 1) prevday = ProtocolBase.strftime(startdate, "%A") one_day = datetime.timedelta(1) testdate = startdate + one_day while testdate < enddate: if (testdate.day == 1 and testdate.month == 1 and (testdate.year % 100 == 0)): print("Testing century", testdate.year) day = ProtocolBase.strftime(testdate, "%A") if nextday[prevday] != day: raise AssertionError(str(testdate)) prevday = day testdate = testdate + one_day
def test_time_usec(self): # python's datetime and time only accept ints between [0, 1e6[ # if the incoming data is 999999.8 microseconds, rounding it up means # adding 1 second to time. For many reasons, we want to avoid that. (see # http://bugs.python.org/issue1487389) That's why 999999.8 usec is # rounded to 999999. # rounding 0.1 µsec down t = ProtocolBase().from_unicode(Time, "12:12:12.0000001") self.assertEquals(datetime.time(12, 12, 12), t) # rounding 1.5 µsec up. 0.5 is rounded down by python 3 and up by # python 2 so we test with 1.5 µsec instead. frikkin' nonsense. t = ProtocolBase().from_unicode(Time, "12:12:12.0000015") self.assertEquals(datetime.time(12, 12, 12, 2), t) # rounding 999998.8 µsec up t = ProtocolBase().from_unicode(Time, "12:12:12.9999988") self.assertEquals(datetime.time(12, 12, 12, 999999), t) # rounding 999999.1 µsec down t = ProtocolBase().from_unicode(Time, "12:12:12.9999991") self.assertEquals(datetime.time(12, 12, 12, 999999), t) # rounding 999999.8 µsec down, not up. t = ProtocolBase().from_unicode(Time, "12:12:12.9999998") self.assertEquals(datetime.time(12, 12, 12, 999999), t)
def __init__(self, app=None, validator=None, xml_declaration=True, cleanup_namespaces=False): ProtocolBase.__init__(self, app, validator) self.xml_declaration = xml_declaration self.cleanup_namespaces = cleanup_namespaces self.serialization_handlers = cdict({ AnyXml: xml_to_parent_element, Alias: alias_to_parent_element, Fault: fault_to_parent_element, AnyDict: dict_to_parent_element, EnumBase: enum_to_parent_element, ModelBase: base_to_parent_element, ByteArray: binary_to_parent_element, Attachment: binary_to_parent_element, ComplexModelBase: complex_to_parent_element, }) self.deserialization_handlers = cdict({ AnyXml: xml_from_element, Fault: fault_from_element, AnyDict: dict_from_element, EnumBase: enum_from_element, ModelBase: base_from_element, Unicode: unicode_from_element, ByteArray: binary_from_element, Attachment: binary_from_element, ComplexModelBase: complex_from_element, Iterable: iterable_from_element, Array: array_from_element, }) self.log_messages = (logger.level == logging.DEBUG)
def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, interface=None): self.services = tuple(services) self.tns = tns self.name = name if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase() self.in_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.in_protocol.message = self.in_protocol.REQUEST if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase() self.out_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.out_protocol.message = self.out_protocol.RESPONSE register_application(self) self.reinitialize()
def test_datetime_usec(self): # see the comments on time test for why the rounding here is weird # rounding 0.1 µsec down dt = ProtocolBase().from_unicode(DateTime, "2015-01-01 12:12:12.0000001") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12), dt) # rounding 1.5 µsec up. 0.5 is rounded down by python 3 and up by # python 2 so we test with 1.5 µsec instead. frikkin' nonsense. dt = ProtocolBase().from_unicode(DateTime, "2015-01-01 12:12:12.0000015") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 2), dt) # rounding 999998.8 µsec up dt = ProtocolBase().from_unicode(DateTime, "2015-01-01 12:12:12.9999988") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt) # rounding 999999.1 µsec down dt = ProtocolBase().from_unicode(DateTime, "2015-01-01 12:12:12.9999991") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt) # rounding 999999.8 µsec down, not up. dt = ProtocolBase().from_unicode(DateTime, "2015-01-01 12:12:12.9999998") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt)
def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, config=None): self.services = tuple(services) self.tns = tns self.name = name self.config = config if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase() self.in_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.in_protocol.message = self.in_protocol.REQUEST if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase() self.out_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.out_protocol.message = self.out_protocol.RESPONSE register_application(self)
def test_self_referential_array_workaround(self): from spyne.util.dictdoc import get_object_as_dict class Category(ComplexModel): id = Integer(min_occurs=1, max_occurs=1, nillable=False) Category._type_info['children'] = Array(Category) parent = Category() parent.children = [Category(id=0), Category(id=1)] d = get_object_as_dict(parent, Category) pprint(d) assert d['children'][0]['id'] == 0 assert d['children'][1]['id'] == 1 class SoapService(ServiceBase): @rpc(_returns=Category) def view_categories(ctx): pass Application([SoapService], 'service.soap', in_protocol=ProtocolBase(), out_protocol=ProtocolBase())
def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, interface=None): self.services = tuple(services) self.tns = tns self.name = name if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase(self) else: self.in_protocol.set_app(self) if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase(self) else: self.out_protocol.set_app(self) register_application(self) self.reinitialize()
def test_datetime_usec(self): # see the comments on time test for why the rounding here is weird # rounding 0.1 µsec down dt = ProtocolBase().from_string(DateTime, "2015-01-01 12:12:12.0000001") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12), dt) # rounding 0.5 µsec up dt = ProtocolBase().from_string(DateTime, "2015-01-01 12:12:12.0000005") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 1), dt) # rounding 999998.8 µsec up dt = ProtocolBase().from_string(DateTime, "2015-01-01 12:12:12.9999988") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt) # rounding 999999.1 µsec down dt = ProtocolBase().from_string(DateTime, "2015-01-01 12:12:12.9999991") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt) # rounding 999999.8 µsec down, not up. dt = ProtocolBase().from_string(DateTime, "2015-01-01 12:12:12.9999998") self.assertEquals(datetime.datetime(2015, 1, 1, 12, 12, 12, 999999), dt)
def __init__(self, services, tns, name=None, prefix_namespace=None, names_parts_in_messages=None, in_protocol=None, out_protocol=None, config=None, classes=()): self.services = tuple(services) self.tns = tns self.name = name self.config = config self.classes = classes self.names_parts_in_messages = names_parts_in_messages if prefix_namespace is None: self.prefix_namespace = DEFAULT_PREFIX_NAMESPACE else: self.prefix_namespace = prefix_namespace if self.name is None: self.name = self.__class__.__name__.split('.')[-1] logger.info("Initializing application {%s}%s...", self.tns, self.name) self.event_manager = EventManager(self) self.error_handler = None self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase() if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase() self.check_unique_method_keys() # is this really necessary nowadays? # this needs to be after protocol assignments to give _static_when # functions as much info as possible about the application self.interface = Interface(self) # set_app needs to be after interface init because the protocols use it. self.in_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.in_protocol.message = self.in_protocol.REQUEST self.out_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.out_protocol.message = self.out_protocol.RESPONSE register_application(self)
def test_time(self): n = datetime.time(1, 2, 3, 4) ret = ProtocolBase().to_bytes(Time, n) self.assertEquals(ret, n.isoformat()) dt = ProtocolBase().from_unicode(Time, ret) self.assertEquals(n, dt)
def test_time(self): n = datetime.time(1, 2, 3, 4) ret = ProtocolBase.to_string(Time, n) self.assertEquals(ret, n.isoformat()) dt = ProtocolBase.from_string(Time, ret) self.assertEquals(n, dt)
def test_date(self): n = datetime.date(2011,12,13) ret = ProtocolBase.to_string(Date, n) self.assertEquals(ret, n.isoformat()) dt = ProtocolBase.from_string(Date, ret) self.assertEquals(n, dt)
def test_date(self): n = datetime.date(2011, 12, 13) ret = ProtocolBase().to_unicode(Date, n) self.assertEquals(ret, n.isoformat()) dt = ProtocolBase().from_unicode(Date, ret) self.assertEquals(n, dt)
def test_unicode_cast(self): # to_unicode is dumb enough to pass an int straight back # this normally fails later in the pipeline assert isinstance(ProtocolBase().to_unicode(Unicode, 1), six.integer_types) # when cast is passed, the return value is a proper string assert isinstance(ProtocolBase().to_unicode(Unicode(cast=str), 1), six.string_types)
def test_datetime_ancient(self): t = DateTime(dt_format="%Y-%m-%d %H:%M:%S") # to trigger strftime v = datetime.datetime(1881, 1, 1) vs = '1881-01-01 00:00:00' dt = ProtocolBase().from_unicode(t, vs) self.assertEquals(v, dt) dt = ProtocolBase().to_unicode(t, v) self.assertEquals(vs, dt)
def __init__(self, app=None, validator=None, xml_declaration=True, cleanup_namespaces=True, encoding='UTF-8', pretty_print=False): ProtocolBase.__init__(self, app, validator) self.xml_declaration = xml_declaration self.cleanup_namespaces = cleanup_namespaces self.encoding = encoding self.pretty_print = pretty_print self.serialization_handlers = cdict({ AnyXml: xml_to_parent_element, Alias: alias_to_parent_element, Fault: fault_to_parent_element, AnyDict: dict_to_parent_element, AnyHtml: html_to_parent_element, EnumBase: enum_to_parent_element, ModelBase: base_to_parent_element, ByteArray: byte_array_to_parent_element, Attachment: attachment_to_parent_element, XmlAttribute: xmlattribute_to_parent_element, ComplexModelBase: complex_to_parent_element, }) self.deserialization_handlers = cdict({ AnyXml: xml_from_element, Fault: fault_from_element, AnyDict: dict_from_element, EnumBase: enum_from_element, ModelBase: base_from_element, Unicode: unicode_from_element, ByteArray: byte_array_from_element, Attachment: attachment_from_element, ComplexModelBase: complex_from_element, Alias: alias_from_element, Iterable: iterable_from_element, Array: array_from_element, }) self.log_messages = (logger.level == logging.DEBUG) self.parser = etree.XMLParser(remove_comments=True)
def test_duration_xml_duration(self): dur = datetime.timedelta(days=5 + 30 + 365, hours=1, minutes=1, seconds=12, microseconds=8e5) str1 = 'P400DT3672.8S' str2 = 'P1Y1M5DT1H1M12.8S' self.assertEquals(dur, ProtocolBase().from_string(Duration, str1)) self.assertEquals(dur, ProtocolBase().from_string(Duration, str2)) self.assertEquals(dur, ProtocolBase().from_string(Duration, ProtocolBase().to_string(Duration, dur)))
def test_duration_xml_duration(self): dur = datetime.timedelta(days=5 + 30 + 365, hours=1, minutes=1, seconds=12, microseconds=8e5) str1 = 'P400DT3672.8S' str2 = 'P1Y1M5DT1H1M12.8S' self.assertEquals(dur, ProtocolBase.from_string(Duration, str1)) self.assertEquals(dur, ProtocolBase.from_string(Duration, str2)) self.assertEquals(dur, ProtocolBase.from_string(Duration, ProtocolBase.to_string(Duration, dur)))
def test_limits(self): try: ProtocolBase().from_string(Integer, "1" * (Integer.__max_str_len__ + 1)) except: pass else: raise Exception("must fail.") ProtocolBase().from_string(UnsignedInteger, "-1") # This is not supposed to fail. assert not UnsignedInteger.validate_native(UnsignedInteger, -1)
def set_app(self, value): ProtocolBase.set_app(self, value) self.validation_schema = None if self.validator is self.SCHEMA_VALIDATION and value is not None: from spyne.interface.xml_schema import XmlSchema xml_schema = XmlSchema(value.interface) xml_schema.build_validation_schema() self.validation_schema = xml_schema.validation_schema
def set_app(self, value): ProtocolBase.set_app(self, value) self.validation_schema = None if value: from spyne.interface.xml_schema import XmlSchema xml_schema = XmlSchema(value.interface) xml_schema.build_validation_schema() self.validation_schema = xml_schema.validation_schema
def __init__(self, app=None, validator=None, mime_type=None, ignore_uncap=False, ignore_wrappers=True, complex_as=dict, ordered=False): ProtocolBase.__init__(self, app, validator, mime_type, ignore_uncap) self.ignore_wrappers = ignore_wrappers self.complex_as = complex_as self.ordered = ordered if ordered: raise NotImplementedError('ordered == False') self.stringified_types = (DateTime, Date, Time, Uuid, Duration, AnyXml, AnyHtml)
def test_datetime_serialize_as(self): i = 1234567890123456 v = datetime.datetime.fromtimestamp(i / 1e6) assert ProtocolBase().to_string(DateTime(serialize_as='sec'), v) == i // 1e6 assert ProtocolBase().to_string(DateTime(serialize_as='sec_float'), v) == i / 1e6 assert ProtocolBase().to_string(DateTime(serialize_as='msec'), v) == i // 1e3 assert ProtocolBase().to_string(DateTime(serialize_as='msec_float'), v) == i / 1e3 assert ProtocolBase().to_string(DateTime(serialize_as='usec'), v) == i
def test_canonical_case(self): class TestSelfReference(ComplexModel): self_reference = SelfReference assert (TestSelfReference._type_info['self_reference'] is TestSelfReference) class SoapService(ServiceBase): @rpc(_returns=TestSelfReference) def view_categories(ctx): pass Application([SoapService], 'service.soap', in_protocol=ProtocolBase(), out_protocol=ProtocolBase())
def _to_value(cls, class_, value, k=None): if issubclass(class_, ComplexModelBase): return cls._to_dict(class_, value, k) if issubclass(class_, DateTime): return ProtocolBase.to_string(class_, value) if issubclass(class_, Decimal): if class_.Attributes.format is None: return value else: return ProtocolBase.to_string(class_, value) return value
def __init__( self, app=None, validator=None, xml_declaration=True, cleanup_namespaces=True, encoding="UTF-8", pretty_print=False, ): ProtocolBase.__init__(self, app, validator) self.xml_declaration = xml_declaration self.cleanup_namespaces = cleanup_namespaces self.encoding = encoding self.pretty_print = pretty_print self.serialization_handlers = cdict( { AnyXml: xml_to_parent_element, Alias: alias_to_parent_element, Fault: fault_to_parent_element, AnyDict: dict_to_parent_element, AnyHtml: html_to_parent_element, EnumBase: enum_to_parent_element, ModelBase: base_to_parent_element, ByteArray: byte_array_to_parent_element, Attachment: attachment_to_parent_element, ComplexModelBase: complex_to_parent_element, } ) self.deserialization_handlers = cdict( { AnyXml: xml_from_element, Fault: fault_from_element, AnyDict: dict_from_element, EnumBase: enum_from_element, ModelBase: base_from_element, Unicode: unicode_from_element, ByteArray: byte_array_from_element, Attachment: attachment_from_element, ComplexModelBase: complex_from_element, Alias: alias_from_element, Iterable: iterable_from_element, Array: array_from_element, } ) self.log_messages = logger.level == logging.DEBUG self.parser = etree.XMLParser(remove_comments=True)
def serialize(self, ctx, message): assert message in (self.REQUEST, self.RESPONSE) self.event_manager.fire_event('before_serialize', ctx) if ctx.out_error is not None: ctx.out_document = [ProtocolBase.to_dict(ctx.out_error.__class__, ctx.out_error)] else: # get the result message if message is self.REQUEST: out_type = ctx.descriptor.in_message elif message is self.RESPONSE: out_type = ctx.descriptor.out_message if out_type is None: return out_type_info = out_type._type_info # instantiate the result message out_instance = out_type() # assign raw result to its wrapper, result_message for i in range(len(out_type_info)): attr_name = out_type_info.keys()[i] setattr(out_instance, attr_name, ctx.out_object[i]) ctx.out_document = self._object_to_doc(out_type, out_instance, skip_depth=self.skip_depth) self.event_manager.fire_event('after_serialize', ctx)
def test_limits(self): try: ProtocolBase.from_string(Integer, "1" * (Integer.__max_str_len__ + 1)) except: pass else: raise Exception("must fail.") ProtocolBase.from_string(UnsignedInteger, "-1") # This is not supposed to fail. try: UnsignedInteger.validate_native(-1) # This is supposed to fail. except: pass else: raise Exception("must fail.")
def test_datetime_deserialize(self): i = 1234567890123456 v = datetime.datetime.fromtimestamp(i / 1e6) assert ProtocolBase().from_unicode( DateTime(serialize_as='sec'), i//1e6) == \ datetime.datetime.fromtimestamp(i//1e6) assert ProtocolBase().from_unicode( DateTime(serialize_as='sec_float'), i/1e6) == v assert ProtocolBase().from_unicode( DateTime(serialize_as='msec'), i//1e3) == \ datetime.datetime.fromtimestamp(i/1e3//1000) assert ProtocolBase().from_unicode( DateTime(serialize_as='msec_float'), i/1e3) == v assert ProtocolBase().from_unicode( DateTime(serialize_as='usec'), i) == v
def __init__(self, app=None, validator=None): """Protocol that returns the response object as a html microformat. See https://en.wikipedia.org/wiki/Microformats for more info. The simple flavour is like the XmlDocument protocol, but returns data in <div> or <span> tags. :param app: A spyne.application.Application instance. :param validator: The validator to use. Ignored. :param root_tag: The type of the root tag that encapsulates the return data. :param child_tag: The type of the tag that encapsulates the fields of the returned object. :param field_name_attr: The name of the attribute that will contain the field names of the complex object children. :param field_type_attr: The name of the attribute that will contain the type names of the complex object children. """ ProtocolBase.__init__(self, app, validator)
def __init__(self, app=None, validator=None, skip_depth=0): """Protocol that returns the response object as a html microformat. See https://en.wikipedia.org/wiki/Microformats for more info. The simple flavour is like the XmlDocument protocol, but returns data in <div> or <span> tags. :param app: A spyne.application.Application instance. :param validator: The validator to use. Ignored. :param root_tag: The type of the root tag that encapsulates the return data. :param child_tag: The type of the tag that encapsulates the fields of the returned object. :param field_name_attr: The name of the attribute that will contain the field names of the complex object children. :param field_type_attr: The name of the attribute that will contain the type names of the complex object children. :param skip_depth: Number of wrapper classes to ignore. This is typically one of (0, 1, 2) but higher numbers may also work for your case. """ ProtocolBase.__init__(self, app, validator, skip_depth=skip_depth)
def test_duration(self): d = ProtocolBase().to_unicode(Duration, timedelta(0, 45)) class SomeService(Service): @srpc(Duration, _returns=Duration) def some_call(p): print(p) print(type(p)) assert type(p) == timedelta return p ctx = _dry_me([SomeService], {"some_call": [d]}) s = self.loads(b''.join(ctx.out_string)) d = {"some_callResponse": {"some_callResult": d}} print(s) print(d) assert s == d
def test_uuid_deserialize(self): value = uuid.UUID('12345678123456781234567812345678') assert ProtocolBase().from_unicode(Uuid, '12345678-1234-5678-1234-567812345678') == value assert ProtocolBase().from_unicode(Uuid(serialize_as='hex'), '12345678123456781234567812345678') == value assert ProtocolBase().from_unicode(Uuid(serialize_as='urn'), 'urn:uuid:12345678-1234-5678-1234-567812345678') == value assert ProtocolBase().from_string(Uuid(serialize_as='bytes'), b'\x124Vx\x124Vx\x124Vx\x124Vx') == value assert ProtocolBase().from_string(Uuid(serialize_as='bytes_le'), b'xV4\x124\x12xV\x124Vx\x124Vx') == value assert ProtocolBase().from_unicode(Uuid(serialize_as='fields'), (305419896, 4660, 22136, 18, 52, 95073701484152)) == value assert ProtocolBase().from_unicode(Uuid(serialize_as='int'), 24197857161011715162171839636988778104) == value
def test_uuid_serialize(self): value = uuid.UUID('12345678123456781234567812345678') assert ProtocolBase().to_bytes(Uuid, value) == \ '12345678-1234-5678-1234-567812345678' assert ProtocolBase().to_bytes(Uuid(serialize_as='hex'), value) == \ '12345678123456781234567812345678' assert ProtocolBase().to_bytes(Uuid(serialize_as='urn'), value) == \ 'urn:uuid:12345678-1234-5678-1234-567812345678' assert ProtocolBase().to_bytes(Uuid(serialize_as='bytes'), value) == \ b'\x124Vx\x124Vx\x124Vx\x124Vx' assert ProtocolBase().to_bytes(Uuid(serialize_as='bytes_le'), value) == \ b'xV4\x124\x12xV\x124Vx\x124Vx' assert ProtocolBase().to_bytes(Uuid(serialize_as='fields'), value) == \ (305419896, 4660, 22136, 18, 52, 95073701484152) assert ProtocolBase().to_bytes(Uuid(serialize_as='int'), value) == \ 24197857161011715162171839636988778104
def flat_dict_to_object(cls, doc, inst_class, validator=None, hier_delim="_"): """Converts a flat dict to a native python object. See :func:`spyne.model.complex.ComplexModelBase.get_flat_type_info`. """ simple_type_info = inst_class.get_simple_type_info(inst_class) inst = inst_class.get_deserialization_instance() # this is for validating cls.Attributes.{min,max}_occurs frequencies = defaultdict(lambda: defaultdict(int)) for orig_k, v in doc.items(): k = RE_HTTP_ARRAY_INDEX.sub("", orig_k) member = simple_type_info.get(k, None) if member is None: logger.debug("discarding field %r" % k) continue value = getattr(inst, k, None) if value is None: value = [] # extract native values from the list of strings that come from the # http dict. for v2 in v: if (validator is cls.SOFT_VALIDATION and not member.type.validate_string(member.type, v2)): raise ValidationError(v2) if issubclass(member.type, (File, ByteArray)): if isinstance(v2, str) or isinstance(v2, unicode): native_v2 = ProtocolBase.from_string(member.type, v2) else: native_v2 = v2 else: native_v2 = ProtocolBase.from_string(member.type, v2) if (validator is cls.SOFT_VALIDATION and not member.type.validate_native(member.type, native_v2)): raise ValidationError(v2) value.append(native_v2) # assign the native value to the relevant class in the nested object # structure. ccls, cinst = inst_class, inst ctype_info = inst_class.get_flat_type_info(inst_class) idx, nidx = 0, 0 pkey = member.path[0] cfreq_key = inst_class, idx indexes = deque(RE_HTTP_ARRAY_INDEX.findall(orig_k)) for i in range(len(member.path) - 1): pkey = member.path[i] nidx = 0 ncls, ninst = ctype_info[pkey], getattr(cinst, pkey, None) mo = ncls.Attributes.max_occurs if ninst is None: ninst = ncls.get_deserialization_instance() if mo > 1: ninst = [ninst] setattr(cinst, pkey, ninst) frequencies[cfreq_key][pkey] += 1 if mo > 1: if len(indexes) == 0: raise ValidationError(orig_k, "%r requires index information.") nidx = int(indexes.popleft()) if nidx > len(ninst) or nidx < 0: raise ValidationError(orig_k, "%%r Invalid array index %d." % idx) if nidx == len(ninst): ninst.append(ncls.get_deserialization_instance()) frequencies[cfreq_key][pkey] += 1 cinst = ninst[nidx] else: cinst = ninst cfreq_key = cfreq_key + (ncls, nidx) ccls, idx = ncls, nidx ctype_info = ncls._type_info frequencies[cfreq_key][member.path[-1]] += len(value) if member.type.Attributes.max_occurs > 1: v = getattr(cinst, member.path[-1], None) if v is None: setattr(cinst, member.path[-1], value) else: v.extend(value) logger.debug("\tset array %r(%r) = %r" % (member.path, pkey, value)) else: setattr(cinst, member.path[-1], value[0]) logger.debug("\tset default %r(%r) = %r" % (member.path, pkey, value)) if validator is cls.SOFT_VALIDATION: for k, d in frequencies.items(): check_freq_dict(k[-2], d) return inst
def __init__(self, app=None): ProtocolBase.__init__(self, app, validator=None) self.length = 500 # if you change this, you should re-scale the svg file
from datetime import date, datetime from spyne import D, Integer, ModelBase, Date, DateTime, IpAddress, Decimal from spyne.protocol import ProtocolBase from spyne.util import six from spyne.util.cdict import cdict if six.PY2: bytes = str else: unicode = str _prot = ProtocolBase() MAP = cdict({ ModelBase: cdict({ object: lambda _: _, bytes: lambda _: _.strip(), unicode: lambda _: _.strip(), }), Decimal: cdict({ D: lambda _: _, int: lambda _: D(_), bytes: lambda s: None if s.strip() == '' else D(s.strip()), unicode: lambda s: None if s.strip() == u'' else D(s.strip()), }),
class Application(object): """The Application class is the glue between one or more service definitions, input and output protocols. :param services: An iterable of ServiceBase subclasses that defines the exposed services. :param tns: The targetNamespace attribute of the exposed service. :param name: The optional name attribute of the exposed service. The default is the name of the application class which is by default 'Application'. :param in_protocol: A ProtocolBase instance that denotes the input protocol. It's only optional for NullServer transport. :param out_protocol: A ProtocolBase instance that denotes the output protocol. It's only optional for NullServer transport. :param config: An arbitrary python object to store random global data. Supported events: * ``method_call``: Called right before the service method is executed * ``method_return_object``: Called right after the service method is executed * ``method_exception_object``: Called when an exception occurred in a service method, before the exception is serialized. * ``method_context_created``: Called from the constructor of the MethodContext instance. * ``method_context_closed``: Called from the ``close()`` function of the MethodContext instance, which in turn is called by the transport when the response is fully sent to the client (or in the client case, the response is fully received from server). """ transport = None def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, config=None): self.services = tuple(services) self.tns = tns self.name = name self.config = config if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase() self.in_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.in_protocol.message = self.in_protocol.REQUEST if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase() self.out_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.out_protocol.message = self.out_protocol.RESPONSE register_application(self) def process_request(self, ctx): """Takes a MethodContext instance. Returns the response to the request as a native python object. If the function throws an exception, it returns None and sets the exception object to ctx.out_error. Overriding this method would break event management. So this is not meant to be overridden unless you know what you're doing. """ try: # fire events self.event_manager.fire_event('method_call', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event('method_call', ctx) # in object is always a sequence of incoming values. We need to fix # that for bare mode. if ctx.descriptor.body_style is BODY_STYLE_BARE: ctx.in_object = [ctx.in_object] elif ctx.descriptor.body_style is BODY_STYLE_EMPTY: ctx.in_object = [] # call user method ctx.out_object = self.call_wrapper(ctx) # out object is always a sequence of return values. see # MethodContext docstrings for more info if ctx.descriptor.body_style is not BODY_STYLE_WRAPPED or \ len(ctx.descriptor.out_message._type_info) <= 1: # if it's not a wrapped method, OR there's just one return type # we wrap it ourselves ctx.out_object = [ctx.out_object] # Now that the processing is switched to the outgoing message, # point ctx.protocol to ctx.out_protocol ctx.protocol = ctx.outprot_ctx # fire events self.event_manager.fire_event('method_return_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_return_object', ctx) except Redirect as e: try: e.do_redirect() ctx.out_object = [None] # Now that the processing is switched to the outgoing message, # point ctx.protocol to ctx.out_protocol ctx.protocol = ctx.outprot_ctx # fire events self.event_manager.fire_event('method_redirect', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_redirect', ctx) except Exception as e: logger_server.exception(e) ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) # fire events self.event_manager.fire_event('method_redirect_exception', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_redirect_exception', ctx) except Fault as e: if e.faultcode == 'Client' or e.faultcode.startswith('Client.'): logger_client.exception(e) else: logger.exception(e) ctx.out_error = e # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx) # we don't catch BaseException because we actually don't want to catch # "system-exiting" exceptions. See: # https://docs.python.org/2/library/exceptions.html#exceptions.Exception except Exception as e: logger_server.critical(e, **{'exc_info': 1}) ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx) def call_wrapper(self, ctx): """This method calls the call_wrapper method in the service definition. This can be overridden to make an application-wide custom exception management. """ retval = None # service rpc if ctx.descriptor.no_self: retval = ctx.descriptor.service_class.call_wrapper(ctx) # class rpc else: cls = ctx.descriptor.parent_class if cls.__orig__ is not None: cls = cls.__orig__ inst = cls.__respawn__(ctx) if inst is None: raise RespawnError('{%s}%s' % (cls.get_namespace(), cls.get_type_name())) in_cls = ctx.descriptor.in_message args = ctx.in_object if args is None: args = [] elif ctx.descriptor.body_style is BODY_STYLE_WRAPPED and \ len(in_cls.get_flat_type_info(in_cls)) <= 1: args = [] else: args = args[1:] if ctx.descriptor.service_class is not None: ctx.in_object = [inst, ctx] ctx.in_object.extend(args) # hack to make sure inst goes first ctx.descriptor.no_ctx = True retval = ctx.descriptor.service_class.call_wrapper(ctx) elif ctx.function is not None: if ctx.descriptor.no_ctx: retval = ctx.function(inst, *args) else: retval = ctx.function(inst, ctx, *args) return retval def _has_callbacks(self): return self.interface._has_callbacks() def reinitialize(self, server): """This is normally called on transport instantiation by ServerBase""" seen = set() from spyne import MethodDescriptor for d in self.interface.method_id_map.values(): assert isinstance(d, MethodDescriptor) if d.aux is not None and not id(d.aux) in seen: d.aux.initialize(server) seen.add(id(d.aux)) if d.service_class is not None and not id(d.service_class) in seen: d.service_class.initialize(server) seen.add(id(d.service_class)) def __hash__(self): return hash(tuple((id(s) for s in self.services)))
class Application(object): """The Application class is the glue between one or more service definitions, input and output protocols. :param services: An iterable of ServiceBase subclasses that defines the exposed services. :param tns: The targetNamespace attribute of the exposed service. :param name: The optional name attribute of the exposed service. The default is the name of the application class which is by default 'Application'. :param in_protocol: A ProtocolBase instance that denotes the input protocol. It's only optional for NullServer transport. :param out_protocol: A ProtocolBase instance that denotes the output protocol. It's only optional for NullServer transport. :param interface: Ignored. Kept for backwards-compatibility purposes. Supported events: * ``method_call``: Called right before the service method is executed * ``method_return_object``: Called right after the service method is executed * ``method_exception_object``: Called when an exception occurred in a service method, before the exception is serialized. * ``method_context_created``: Called from the constructor of the MethodContext instance. * ``method_context_closed``: Called from the ``close()`` function of the MethodContext instance, which in turn is called by the transport when the response is fully sent to the client (or in the client case, the response is fully received from server). """ transport = None def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, interface=None): self.services = tuple(services) self.tns = tns self.name = name if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase() self.in_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.in_protocol.message = self.in_protocol.REQUEST if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase() self.out_protocol.set_app(self) # FIXME: this normally is another parameter to set_app but it's kept # separate for backwards compatibility reasons. self.out_protocol.message = self.out_protocol.RESPONSE register_application(self) self.reinitialize() def process_request(self, ctx): """Takes a MethodContext instance. Returns the response to the request as a native python object. If the function throws an exception, it returns None and sets the exception object to ctx.out_error. Overriding this method would break event management. So this is not meant to be overridden unless you know what you're doing. """ try: # fire events self.event_manager.fire_event('method_call', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event('method_call', ctx) # call the method ctx.out_object = self.call_wrapper(ctx) # out object is always an iterable of return values. see # MethodContext docstrings for more info if ctx.descriptor.body_style is not BODY_STYLE_WRAPPED or \ len(ctx.descriptor.out_message._type_info) <= 1: # the return value should already be wrapped by a sequence. ctx.out_object = [ctx.out_object] # fire events self.event_manager.fire_event('method_return_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_return_object', ctx) except Fault as e: if e.faultcode == 'Client' or e.faultcode.startswith('Client.'): logger_client.exception(e) else: logger.exception(e) ctx.out_error = e # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx) except Exception as e: logger.exception(e) ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx) def call_wrapper(self, ctx): """This method calls the call_wrapper method in the service definition. This can be overridden to make an application-wide custom exception management. """ if ctx.descriptor.body_style is BODY_STYLE_BARE: ctx.in_object = [ctx.in_object] elif ctx.descriptor.body_style is BODY_STYLE_EMPTY: ctx.in_object = [] # service rpc if ctx.descriptor.service_class is not None: return ctx.descriptor.service_class.call_wrapper(ctx) # class rpc cls = ctx.descriptor.parent_class if cls.__orig__ is not None: cls = cls.__orig__ inst = cls.__respawn__(ctx) if inst is None: raise ResourceNotFoundError('{%s}%s' % (cls.get_namespace(), cls.get_type_name())) args = ctx.in_object[1:] if ctx.function is not None: if ctx.descriptor.no_ctx: return ctx.function(inst, *args) else: return ctx.function(inst, ctx, *args) def _has_callbacks(self): return self.interface._has_callbacks() def reinitialize(self): from spyne.server import ServerBase server = ServerBase(self) aux_memo = set() for d in self.interface.method_id_map.values(): if d.aux is not None and not id(d.aux) in aux_memo: d.aux.initialize(server) aux_memo.add(id(d.aux)) def __hash__(self): return hash(tuple((id(s) for s in self.services)))
def __init__(self, app=None, validator=None, mime_type=None, tmp_dir=None, tmp_delete_on_close=True): ProtocolBase.__init__(self, app, validator, mime_type) self.tmp_dir = tmp_dir self.tmp_delete_on_close = tmp_delete_on_close
from spyne import D, Integer, ModelBase, Date, DateTime, IpAddress, Decimal from spyne.protocol import ProtocolBase from spyne.util import six from spyne.util.cdict import cdict if six.PY2: bytes = str else: unicode = str _prot = ProtocolBase() MAP = cdict({ ModelBase: cdict({ object: lambda _: _, bytes: lambda _: _.strip(), unicode: lambda _: _.strip(), }), Decimal: cdict({ int: lambda _: D(_), bytes: lambda s: None if s.strip() == '' else D(s.strip()), unicode: lambda s: None if s.strip() == u'' else D(s.strip()), }), Integer: cdict({ int: lambda _: _, bytes: lambda s: None if s.strip() == '' else int(s.strip()),
def __init__(self, app=None, validator=None, xml_declaration=True, cleanup_namespaces=True, encoding=None, pretty_print=False, attribute_defaults=False, dtd_validation=False, load_dtd=False, no_network=True, ns_clean=False, recover=False, remove_blank_text=False, remove_pis=True, strip_cdata=True, resolve_entities=False, huge_tree=False, compact=True ): ProtocolBase.__init__(self, app, validator) self.xml_declaration = xml_declaration self.cleanup_namespaces = cleanup_namespaces if encoding is None: self.encoding = 'UTF-8' else: self.encoding = encoding self.pretty_print = pretty_print self.serialization_handlers = cdict({ AnyXml: xml_to_parent_element, Alias: alias_to_parent_element, Fault: fault_to_parent_element, AnyDict: dict_to_parent_element, AnyHtml: html_to_parent_element, EnumBase: enum_to_parent_element, ModelBase: base_to_parent_element, ByteArray: byte_array_to_parent_element, Attachment: attachment_to_parent_element, XmlAttribute: xmlattribute_to_parent_element, ComplexModelBase: complex_to_parent_element, }) self.deserialization_handlers = cdict({ AnyXml: xml_from_element, Fault: fault_from_element, AnyDict: dict_from_element, EnumBase: enum_from_element, ModelBase: base_from_element, Unicode: unicode_from_element, ByteArray: byte_array_from_element, Attachment: attachment_from_element, ComplexModelBase: complex_from_element, Alias: alias_from_element, Iterable: iterable_from_element, Array: array_from_element, }) self.log_messages = (logger.level == logging.DEBUG) self.parser_kwargs = dict( attribute_defaults=attribute_defaults, dtd_validation=dtd_validation, load_dtd=load_dtd, no_network=no_network, ns_clean=ns_clean, recover=recover, remove_blank_text=remove_blank_text, remove_comments=True, remove_pis=remove_pis, strip_cdata=strip_cdata, resolve_entities=resolve_entities, huge_tree=huge_tree, compact=compact, encoding=encoding, )
class Application(object): '''The Application class is the glue between one or more service definitions, input and output protocols. :param services: An iterable of ServiceBase subclasses that define the exposed services. :param tns: The targetNamespace attribute of the exposed service. :param name: The optional name attribute of the exposed service. The default is the name of the application class which is by default 'Application'. :param in_protocol: A ProtocolBase instance that denotes the input protocol. It's only optional for NullServer transport. :param out_protocol: A ProtocolBase instance that denotes the output protocol. It's only optional for NullServer transport. :param interface: Ignored. Kept for backwards-compatibility purposes. Supported events: * method_call: Called right before the service method is executed * method_return_object: Called right after the service method is executed * method_exception_object: Called when an exception occurred in a service method, before the exception is serialized. * method_context_created: Called from the constructor of the MethodContext instance. * method_context_closed: Called from the ``close()`` function of the MethodContext instance, which in turn is called by the transport when the response is fully sent to the client (or in the client case, the response is fully received from server). ''' transport = None def __init__(self, services, tns, name=None, in_protocol=None, out_protocol=None, interface=None): self.services = tuple(services) self.tns = tns self.name = name if self.name is None: self.name = self.__class__.__name__.split('.')[-1] self.event_manager = EventManager(self) self.error_handler = None self.interface = Interface(self) self.in_protocol = in_protocol self.out_protocol = out_protocol if self.in_protocol is None: from spyne.protocol import ProtocolBase self.in_protocol = ProtocolBase(self) else: self.in_protocol.set_app(self) if self.out_protocol is None: from spyne.protocol import ProtocolBase self.out_protocol = ProtocolBase(self) else: self.out_protocol.set_app(self) register_application(self) self.reinitialize() def process_request(self, ctx): """Takes a MethodContext instance. Returns the response to the request as a native python object. If the function throws an exception, it returns None and sets the exception object to ctx.out_error. Overriding this method would break event management. So this is not meant to be overridden unless you know what you're doing. """ try: # fire events self.event_manager.fire_event('method_call', ctx) ctx.service_class.event_manager.fire_event('method_call', ctx) # call the method ctx.out_object = self.call_wrapper(ctx) # out object is always an iterable of return values. see # MethodContext docstrings for more info if len(ctx.descriptor.out_message._type_info) <= 1: # the return value should already be wrapped by a sequence. ctx.out_object = [ctx.out_object] # fire events self.event_manager.fire_event('method_return_object', ctx) ctx.service_class.event_manager.fire_event( 'method_return_object', ctx) except Fault, e: logger.exception(e) ctx.out_error = e # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx) except Exception, e: logger.exception(e) ctx.out_error = Fault('Server', get_fault_string_from_exception(e)) # fire events self.event_manager.fire_event('method_exception_object', ctx) if ctx.service_class is not None: ctx.service_class.event_manager.fire_event( 'method_exception_object', ctx)