def writeDate(self, d): """ Writes a date to the data stream. @type d: Instance of C{datetime.datetime} @param d: The date to be encoded to the AMF0 data stream. """ if isinstance(d, datetime.time): raise pyamf.EncodeError( 'A datetime.time instance was found but AMF0 has no way to ' 'encode time objects. Please use datetime.datetime instead ' '(got:%r)' % (d,) ) # According to the Red5 implementation of AMF0, dates references are # created, but not used. if self.timezone_offset is not None: d -= self.timezone_offset secs = util.get_timestamp(d) tz = 0 self.writeType(TYPE_DATE) self.stream.write_double(secs * 1000.0) self.stream.write_short(tz)
def writeDate(self, n): """ Writes a C{datetime} instance to the stream. @type n: L{datetime} @param n: The C{Date} data to be encoded to the AMF3 data stream. """ if isinstance(n, datetime.time): raise pyamf.EncodeError( 'A datetime.time instance was found but ' 'AMF3 has no way to encode time objects. Please use ' 'datetime.datetime instead (got:%r)' % (n, )) self.stream.write(TYPE_DATE) ref = self.context.getObjectReference(n) if ref != -1: self._writeInteger(ref << 1) return self.context.addObject(n) self.stream.write_uchar(REFERENCE_BIT) if self.timezone_offset is not None: n -= self.timezone_offset ms = util.get_timestamp(n) self.stream.write_double(ms * 1000.0)
def writeType(self, type): """ Writes the type to the stream. @type type: C{int} @param type: ActionScript type. @raise pyamf.EncodeError: AMF0 type is not recognized. """ if type not in ACTIONSCRIPT_TYPES: raise pyamf.EncodeError("Unknown AMF0 type 0x%02x at %d" % (type, self.stream.tell() - 1)) self.stream.write_uchar(type)
def writeElement(self, data): """ Writes the data. @type data: C{mixed} @param data: The data to be encoded to the AMF0 data stream. @raise EncodeError: Cannot find encoder func. """ func = self._writeElementFunc(data) if func is None: raise pyamf.EncodeError("Cannot find encoder func for %r" % (data, )) func(data)
def convert_Decimal(x, encoder): """ Called when an instance of U{decimal.Decimal<http:// docs.python.org/library/decimal.html#decimal-objects>} is about to be encoded to an AMF stream. @return: If the encoder is in 'strict' mode then C{x} will be converted to a float. Otherwise an L{pyamf.EncodeError} with a friendly message is raised. """ if encoder.strict is False: return float(x) raise pyamf.EncodeError( 'Unable to encode decimal.Decimal instances as there is no way to ' 'guarantee exact conversion. Use strict=False to convert to a float.')
def _getObjectAttrs(self, o, alias): obj_attrs = None if alias is not None: attrs = alias.getAttrs(o) if attrs is not None: obj_attrs = {} for at in attrs: obj_attrs[at] = getattr(o, at) if obj_attrs is None: obj_attrs = util.get_attrs(o) if obj_attrs is None: raise pyamf.EncodeError('Unable to determine object attributes') return obj_attrs
def _getObjectAttrs(self, o, alias): """ @raise pyamf.EncodeError: Unable to determine object attributes. """ obj_attrs = None if alias is not None: obj_attrs = {} for attrs in alias.getAttributes(o): obj_attrs.update(attrs) if obj_attrs is None: obj_attrs = util.get_attrs(o) if obj_attrs is None: raise pyamf.EncodeError('Unable to determine object attributes') return obj_attrs
def writeElement(self, data): """ Encodes C{data} to AMF. If the data is not able to be matched to an AMF type, then L{pyamf.EncodeError} will be raised. """ key = type(data) func = None try: func = self._func_cache[key] except KeyError: func = self.getTypeFunc(data) if func is None: raise pyamf.EncodeError('Unable to encode %r (type %r)' % (data, key)) self._func_cache[key] = func func(data)
def convert_Decimal(x, encoder): """ Called when an instance of L{decimal.Decimal} is about to be encoded to an AMF stream. @param x: The L{decimal.Decimal} instance to encode. @param encoder: The L{pyamf.BaseEncoder} instance about to perform the operation. @return: If the encoder is in 'strict' mode then C{x} will be converted to a float. Otherwise an L{pyamf.EncodeError} with a friendly message is raised. """ if encoder is not None and isinstance(encoder, pyamf.BaseEncoder): if encoder.strict is False: return float(x) raise pyamf.EncodeError( 'Unable to encode decimal.Decimal instances as ' 'there is no way to guarantee exact conversion. Use strict=False to ' 'convert to a float.')
def writeElement(self, data): """ Writes the data. @type data: C{mixed} @param data: The data to be encoded to the AMF0 data stream. @raise EncodeError: Cannot find encoder func. """ func = self._writeElementFunc(data) if func is None: raise pyamf.EncodeError("Cannot find encoder func for %r" % (data,)) else: try: func(data) except (KeyboardInterrupt, SystemExit): raise except pyamf.EncodeError: raise except: #raise pyamf.EncodeError("Unable to encode '%r'" % (data,)) raise
def writeDict(self, n): """ Writes a C{dict} to the stream. @type n: C{__builtin__.dict} @param n: The C{dict} data to be encoded to the AMF3 data stream. @raise ValueError: Non C{int}/C{str} key value found in the C{dict} @raise EncodeError: C{dict} contains empty string keys. """ # Design bug in AMF3 that cannot read/write empty key strings # for more info if '' in n: raise pyamf.EncodeError("dicts cannot contain empty string keys") if self.use_proxies: self.writeProxy(n) return self.stream.write(TYPE_ARRAY) ref = self.context.getObjectReference(n) if ref != -1: self._writeInteger(ref << 1) return self.context.addObject(n) # The AMF3 spec demands that all str based indicies be listed first keys = list(n.keys()) int_keys = [] str_keys = [] for x in keys: if isinstance(x, python.int_types): int_keys.append(x) elif isinstance(x, python.str_types): str_keys.append(x) else: raise ValueError("Non int/str key value found in dict") # Make sure the integer keys are within range l = len(int_keys) for x in int_keys: if l < x <= 0: # treat as a string key str_keys.append(x) del int_keys[int_keys.index(x)] int_keys.sort() # If integer keys don't start at 0, they will be treated as strings if len(int_keys) > 0 and int_keys[0] != 0: for x in int_keys: str_keys.append(str(x)) del int_keys[int_keys.index(x)] self._writeInteger(len(int_keys) << 1 | REFERENCE_BIT) for x in str_keys: self.serialiseString(x) self.writeElement(n[x]) self.stream.write_uchar(0x01) for k in int_keys: self.writeElement(n[k])
def encode_time_property(obj, prop, value): # PyAMF supports datetime.datetime objects and won't decide what date to # add to this time value. Users will have to figure it out themselves raise pyamf.EncodeError('ndb.TimeProperty is not supported by PyAMF')
def __writeamf__(self, data_output): raise pyamf.EncodeError("__writeamf__ is not implemented for this class: %s." % self)
def __readamf__(self, data_input): raise pyamf.EncodeError("__readamf__ is not implemented for this class: %s." % self)
def writeFunc(self, *args, **kwargs): """ Functions cannot be serialised. """ raise pyamf.EncodeError("Callables cannot be serialised")
def writeClass(self, *args, **kwargs): """ Classes cannot be serialised. """ raise pyamf.EncodeError("Class objects cannot be serialised")