def default(self, obj): replacer = self.__type_replacements.get(type(obj), None) if replacer: obj = replacer(obj) if isinstance(obj, set): return tuple( obj ) # msgpack module can't deal with sets so we make a tuple out of it if isinstance(obj, uuid.UUID): return str(obj) if isinstance(obj, bytearray): return bytes(obj) if isinstance(obj, complex): return msgpack.ExtType(0x30, struct.pack("dd", obj.real, obj.imag)) if isinstance(obj, datetime.datetime): if obj.tzinfo: raise errors.SerializeError( "msgpack cannot serialize datetime with timezone info") return msgpack.ExtType(0x32, struct.pack("d", obj.timestamp())) if isinstance(obj, datetime.date): return msgpack.ExtType(0x33, struct.pack("l", obj.toordinal())) if isinstance(obj, decimal.Decimal): return str(obj) if isinstance(obj, numbers.Number): return msgpack.ExtType(0x31, str(obj).encode("ascii")) # long return self.class_to_dict(obj)
def connect(location): """ Connect to a Flame server on the given location, for instance localhost:9999 or ./u:unixsock This is just a convenience function to creates an appropriate Pyro proxy. """ if config.SERIALIZER != "pickle": raise errors.SerializeError("Flame requires the pickle serializer") proxy = core.Proxy("PYRO:%s@%s" % (constants.FLAME_NAME, location)) proxy._pyroBind() return proxy
def ext_hook(self, code, data): if code == 0x30: real, imag = struct.unpack("dd", data) return complex(real, imag) if code == 0x31: return int(data) if code == 0x32: return datetime.datetime.fromtimestamp(struct.unpack("d", data)[0]) if code == 0x33: return datetime.date.fromordinal(struct.unpack("l", data)[0]) raise errors.SerializeError("invalid ext code for msgpack: " + str(code))
def start(daemon): """ Create and register a Flame server in the given daemon. Be *very* cautious before starting this: it allows the clients full access to everything on your system. """ if config.FLAME_ENABLED: if set(config.SERIALIZERS_ACCEPTED) != {"pickle"}: raise errors.SerializeError( "Flame requires the pickle serializer exclusively") return daemon.register(Flame(), constants.FLAME_NAME) else: raise errors.SecurityError( "Flame is disabled in the server configuration")
def class_to_dict(cls, obj): """ Convert a non-serializable object to a dict. Partly borrowed from serpent. Not used for the pickle serializer. """ for clazz in cls.__custom_class_to_dict_registry: if isinstance(obj, clazz): return cls.__custom_class_to_dict_registry[clazz](obj) if type(obj) in (set, dict, tuple, list): # we use a ValueError to mirror the exception type returned by serpent and other serializers raise ValueError("can't serialize type " + str(obj.__class__) + " into a dict") if hasattr(obj, "_pyroDaemon"): obj._pyroDaemon = None if isinstance(obj, BaseException): # special case for exceptions return { "__class__": obj.__class__.__module__ + "." + obj.__class__.__name__, "__exception__": True, "args": obj.args, "attributes": vars(obj) # add custom exception attributes } try: value = obj.__getstate__() except AttributeError: pass else: if isinstance(value, dict): return value try: value = dict( vars(obj) ) # make sure we can serialize anything that resembles a dict value[ "__class__"] = obj.__class__.__module__ + "." + obj.__class__.__name__ return value except TypeError: if hasattr(obj, "__slots__"): # use the __slots__ instead of the vars dict value = {} for slot in obj.__slots__: value[slot] = getattr(obj, slot) value[ "__class__"] = obj.__class__.__module__ + "." + obj.__class__.__name__ return value else: raise errors.SerializeError( "don't know how to serialize class " + str(obj.__class__) + " using serializer " + str(cls.__name__) + ". Give it vars() or an appropriate __getstate__")
def get_serializer_by_id(sid): try: return _serializers_by_id[sid] except KeyError: raise errors.SerializeError("no serializer available for id %d" % sid)
def get_serializer(name): try: return _serializers[name] except KeyError: raise errors.SerializeError("serializer '%s' is unknown or not available" % name)
def dict_to_class(cls, data): """ Recreate an object out of a dict containing the class name and the attributes. Only a fixed set of classes are recognized. Not used for the pickle serializer. """ from Pyro4 import core, futures # XXX circular classname = data.get("__class__", "<unknown>") if isinstance(classname, bytes): classname = classname.decode("utf-8") if classname in cls.__custom_dict_to_class_registry: converter = cls.__custom_dict_to_class_registry[classname] return converter(classname, data) if "__" in classname: raise errors.SecurityError("refused to deserialize types with double underscores in their name: " + classname) # for performance, the constructors below are hardcoded here instead of added on a per-class basis to the dict-to-class registry if classname.startswith("Pyro4.core."): if classname == "Pyro4.core.URI": uri = core.URI.__new__(core.URI) uri.__setstate_from_dict__(data["state"]) return uri elif classname == "Pyro4.core.Proxy": proxy = core.Proxy.__new__(core.Proxy) proxy.__setstate_from_dict__(data["state"]) return proxy elif classname == "Pyro4.core.Daemon": daemon = core.Daemon.__new__(core.Daemon) daemon.__setstate_from_dict__(data["state"]) return daemon elif classname.startswith("Pyro4.util."): if classname == "Pyro4.util.SerpentSerializer": return SerpentSerializer() elif classname == "Pyro4.util.PickleSerializer": return PickleSerializer() elif classname == "Pyro4.util.MarshalSerializer": return MarshalSerializer() elif classname == "Pyro4.util.JsonSerializer": return JsonSerializer() elif classname == "Pyro4.util.MsgpackSerializer": return MsgpackSerializer() elif classname == "Pyro4.util.CloudpickleSerializer": return CloudpickleSerializer() elif classname == "Pyro4.util.DillSerializer": return DillSerializer() elif classname.startswith("Pyro4.errors."): errortype = getattr(errors, classname.split('.', 2)[2]) if issubclass(errortype, errors.PyroError): return SerializerBase.make_exception(errortype, data) elif classname == "Pyro4.futures._ExceptionWrapper": ex = data["exception"] if isinstance(ex, dict) and "__class__" in ex: ex = SerializerBase.dict_to_class(ex) return futures._ExceptionWrapper(ex) elif data.get("__exception__", False): if classname in all_exceptions: return SerializerBase.make_exception(all_exceptions[classname], data) # python 2.x: exceptions.ValueError # python 3.x: builtins.ValueError # translate to the appropriate namespace... namespace, short_classname = classname.split('.', 1) if namespace in ("builtins", "exceptions"): if sys.version_info < (3, 0): exceptiontype = getattr(exceptions, short_classname) if issubclass(exceptiontype, BaseException): return SerializerBase.make_exception(exceptiontype, data) else: exceptiontype = getattr(builtins, short_classname) if issubclass(exceptiontype, BaseException): return SerializerBase.make_exception(exceptiontype, data) elif namespace == "sqlite3" and short_classname.endswith("Error"): import sqlite3 exceptiontype = getattr(sqlite3, short_classname) if issubclass(exceptiontype, BaseException): return SerializerBase.make_exception(exceptiontype, data) log.warning("unsupported serialized class: " + classname) raise errors.SerializeError("unsupported serialized class: " + classname)