示例#1
0
 def __asynccall(self, asyncresult, args, kwargs):
     try:
         # use a copy of the proxy otherwise calls would be serialized,
         # and use contextmanager to close the proxy after we're done
         with self.__proxy.__copy__() as proxy:
             value = proxy._pyroInvoke(self.__name, args, kwargs)
         asyncresult.value = value
     except Exception:
         # ignore any exceptions here, return them as part of the async result instead
         asyncresult.value = futures._ExceptionWrapper(sys.exc_info()[1])
示例#2
0
    def _pyro_remote_call(self, msg):
        log = logger.debug
        result = []

        # Deserialize
        request_flags = msg.flags
        request_seq = msg.seq
        serializer = util.get_serializer_by_id(msg.serializer_id)
        objId, method, vargs, kwargs = serializer.deserializeCall(msg.data, compressed=msg.flags & Pyro4.message.FLAGS_COMPRESSED)
        del msg  # invite GC to collect the object, don't wait for out-of-scope
        # Individual or batch
        log("Searching for object %s" % str(objId))
        obj = self.factory.objectsById.get(objId)
        log("Found object with type %s" % str(type(obj)))
        if obj is not None:
            # Sanitize kwargs
            if kwargs and sys.version_info < (2, 6, 5) and os.name != "java":
                # Python before 2.6.5 doesn't accept unicode keyword arguments
                kwargs = dict((str(k), kwargs[k]) for k in kwargs)
            if request_flags & Pyro4.message.FLAGS_BATCH:
                for method, vargs, kwargs in vargs:
                    log("Running call %s with vargs %s and kwargs %s agasint object %s" %
                        (str(method), str(vargs), str(kwargs), str(obj)))
                    response = yield self._pyro_run_call(obj, method, vargs, kwargs)
                    if isinstance(response, Exception):
                        response = _ExceptionWrapper(response)
                    result.append(response)
                # Return the final value
            else:
                log("Running call %s with vargs %s and kwargs %s agasint object %s" %
                    (str(method), str(vargs), str(kwargs), str(obj)))
                if method == "__getattr__":
                    # special case for direct attribute access (only exposed @properties are accessible)
                    result = util.get_exposed_property_value(obj, vargs[0], only_exposed=Pyro4.config.REQUIRE_EXPOSE)
                elif method == "__setattr__":
                    # special case for direct attribute access (only exposed @properties are accessible)
                    result = util.set_exposed_property_value(obj, vargs[0], vargs[1], only_exposed=Pyro4.config.REQUIRE_EXPOSE)
                else:
                    result = yield self._pyro_run_call(obj, method, vargs, kwargs)
                    if isinstance(result, Failure):
                        exception = result.type(result.value)
                        exception._pyroTraceback = result.tb
                        result = exception
            log("Returning result %s from _remote_call" % pformat(result))
            defer.returnValue(result)
        else:
            log("unknown object requested: %s", objId)
            raise Pyro4.core.errors.DaemonError("unknown object")
示例#3
0
文件: util.py 项目: dean-shaff/Pyro4
 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)
示例#4
0
文件: util.py 项目: irmen/Pyro4
 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)
示例#5
0
 def handleRequest(self, conn):
     """
     Handle incoming Pyro request. Catches any exception that may occur and
     wraps it in a reply to the calling side, as to not make this server side loop
     terminate due to exceptions caused by remote invocations.
     """
     request_flags = 0
     request_seq = 0
     request_serializer_id = util.MarshalSerializer.serializer_id
     wasBatched = False
     isCallback = False
     try:
         msg = Message.recv(
             conn, [Pyro4.message.MSG_INVOKE, Pyro4.message.MSG_PING])
         request_flags = msg.flags
         request_seq = msg.seq
         request_serializer_id = msg.serializer_id
         if Pyro4.config.LOGWIRE:
             log.debug(
                 "daemon wiredata received: msgtype=%d flags=0x%x ser=%d seq=%d data=%r"
                 % (msg.type, msg.flags, msg.serializer_id, msg.seq,
                    msg.data))
         if msg.type == Pyro4.message.MSG_PING:
             # return same seq, but ignore any data (it's a ping, not an echo). Nothing is deserialized.
             msg = Message(Pyro4.message.MSG_PING, b"pong",
                           msg.serializer_id, 0, msg.seq)
             if Pyro4.config.LOGWIRE:
                 log.debug(
                     "daemon wiredata sending: msgtype=%d flags=0x%x ser=%d seq=%d data=%r"
                     % (msg.type, msg.flags, msg.serializer_id, msg.seq,
                        msg.data))
             conn.send(msg.to_bytes())
             return
         if msg.serializer_id not in self.__serializer_ids:
             raise errors.ProtocolError(
                 "message used serializer that is not accepted: %d" %
                 msg.serializer_id)
         serializer = util.get_serializer_by_id(msg.serializer_id)
         objId, method, vargs, kwargs = serializer.deserializeCall(
             msg.data,
             compressed=msg.flags & Pyro4.message.FLAGS_COMPRESSED)
         del msg  # invite GC to collect the object, don't wait for out-of-scope
         obj = self.objectsById.get(objId)
         if obj is not None:
             if kwargs and sys.version_info < (2, 6,
                                               5) and os.name != "java":
                 # Python before 2.6.5 doesn't accept unicode keyword arguments
                 kwargs = dict((str(k), kwargs[k]) for k in kwargs)
             if request_flags & Pyro4.message.FLAGS_BATCH:
                 # batched method calls, loop over them all and collect all results
                 data = []
                 for method, vargs, kwargs in vargs:
                     method = util.resolveDottedAttribute(
                         obj, method, Pyro4.config.DOTTEDNAMES)
                     try:
                         result = method(
                             *vargs, **kwargs
                         )  # this is the actual method call to the Pyro object
                     except Exception:
                         xt, xv = sys.exc_info()[0:2]
                         log.debug(
                             "Exception occurred while handling batched request: %s",
                             xv)
                         xv._pyroTraceback = util.formatTraceback(
                             detailed=Pyro4.config.DETAILED_TRACEBACK)
                         if sys.platform == "cli":
                             util.fixIronPythonExceptionForPickle(
                                 xv, True)  # piggyback attributes
                         data.append(futures._ExceptionWrapper(xv))
                         break  # stop processing the rest of the batch
                     else:
                         data.append(result)
                 wasBatched = True
             else:
                 # normal single method call
                 method = util.resolveDottedAttribute(
                     obj, method, Pyro4.config.DOTTEDNAMES)
                 if request_flags & Pyro4.message.FLAGS_ONEWAY and Pyro4.config.ONEWAY_THREADED:
                     # oneway call to be run inside its own thread
                     thread = threadutil.Thread(target=method,
                                                args=vargs,
                                                kwargs=kwargs)
                     thread.setDaemon(True)
                     thread.start()
                 else:
                     isCallback = getattr(method, "_pyroCallback", False)
                     data = method(
                         *vargs, **kwargs
                     )  # this is the actual method call to the Pyro object
         else:
             log.debug("unknown object requested: %s", objId)
             raise errors.DaemonError("unknown object")
         if request_flags & Pyro4.message.FLAGS_ONEWAY:
             return  # oneway call, don't send a response
         else:
             data, compressed = serializer.serializeData(
                 data, compress=Pyro4.config.COMPRESSION)
             response_flags = 0
             if compressed:
                 response_flags |= Pyro4.message.FLAGS_COMPRESSED
             if wasBatched:
                 response_flags |= Pyro4.message.FLAGS_BATCH
             if Pyro4.config.LOGWIRE:
                 log.debug(
                     "daemon wiredata sending: msgtype=%d flags=0x%x ser=%d seq=%d data=%r"
                     % (Pyro4.message.MSG_RESULT, response_flags,
                        serializer.serializer_id, request_seq, data))
             msg = Message(Pyro4.message.MSG_RESULT, data,
                           serializer.serializer_id, response_flags,
                           request_seq)
             conn.send(msg.to_bytes())
     except Exception:
         xt, xv = sys.exc_info()[0:2]
         if xt is not errors.ConnectionClosedError:
             log.debug("Exception occurred while handling request: %r", xv)
             if not request_flags & Pyro4.message.FLAGS_ONEWAY:
                 # only return the error to the client if it wasn't a oneway call
                 tblines = util.formatTraceback(
                     detailed=Pyro4.config.DETAILED_TRACEBACK)
                 self._sendExceptionResponse(conn, request_seq,
                                             request_serializer_id, xv,
                                             tblines)
         if isCallback or isinstance(
                 xv, (errors.CommunicationError, errors.SecurityError)):
             raise  # re-raise if flagged as callback, communication or security error.
示例#6
0
文件: core.py 项目: adityax10/Pyro4
 def handleRequest(self, conn):
     """
     Handle incoming Pyro request. Catches any exception that may occur and
     wraps it in a reply to the calling side, as to not make this server side loop
     terminate due to exceptions caused by remote invocations.
     """
     flags=0
     seq=0
     wasBatched=False
     isCallback=False
     client_future = None
     try:
         msgType, flags, seq, data = MessageFactory.getMessage(conn, MessageFactory.MSG_INVOKE)
         objId, method, vargs, kwargs=self.serializer.deserialize(
                                        data, compressed=flags & MessageFactory.FLAGS_COMPRESSED)
         del data  # invite GC to collect the object, don't wait for out-of-scope
         obj=self.objectsById.get(objId)
         
         if flags & MessageFactory.FLAGS_ASYNC:
             client_future = vargs[0]
             client_future._pyroOneway.update(["set_cancelled", "set_result", "set_exception", "set_progress"])
             vargs = vargs[1:]
         elif flags & MessageFactory.FLAGS_ASYNC_CANCEL:
             client_future_uri = vargs[0]
         
         if obj is not None:
             if kwargs and sys.version_info<(2, 6, 5) and os.name!="java":
                 # Python before 2.6.5 doesn't accept unicode keyword arguments
                 kwargs = dict((str(k), kwargs[k]) for k in kwargs)
             if flags & MessageFactory.FLAGS_BATCH:
                 # batched method calls, loop over them all and collect all results
                 data=[]
                 for method,vargs,kwargs in vargs:
                     method=util.resolveDottedAttribute(obj, method, Pyro4.config.DOTTEDNAMES)
                     try:
                         result=method(*vargs, **kwargs)   # this is the actual method call to the Pyro object
                     except Exception:
                         xt,xv=sys.exc_info()[0:2]
                         log.debug("Exception occurred while handling batched request: %s", xv)
                         xv._pyroTraceback=util.formatTraceback(detailed=Pyro4.config.DETAILED_TRACEBACK)
                         if sys.platform=="cli":
                             util.fixIronPythonExceptionForPickle(xv, True)  # piggyback attributes
                         data.append(futures._ExceptionWrapper(xv))
                         break   # stop processing the rest of the batch
                     else:
                         data.append(result)
                 wasBatched=True
             elif flags & MessageFactory.FLAGS_ASYNC_CANCEL:
                 data=self._cancelFuture(client_future_uri)
             else:
                 # normal single method call
                 method=util.resolveDottedAttribute(obj, method, Pyro4.config.DOTTEDNAMES)
                 if flags & MessageFactory.FLAGS_ONEWAY and Pyro4.config.ONEWAY_THREADED:
                     # oneway call to be run inside its own thread
                     thread=threadutil.Thread(target=method, args=vargs, kwargs=kwargs)
                     thread.setDaemon(True)
                     thread.start()
                 elif flags & MessageFactory.FLAGS_ASYNC:
                     future=method(*vargs, **kwargs)
                     self._followFuture(future, client_future)
                 else:
                     isCallback=getattr(method, "_pyroCallback", False)
                     data=method(*vargs, **kwargs)   # this is the actual method call to the Pyro object
         else:
             log.debug("unknown object requested: %s", objId)
             raise errors.DaemonError("unknown object")
         if flags & MessageFactory.FLAGS_ONEWAY:
             return   # oneway call, don't send a response
         elif flags & MessageFactory.FLAGS_ASYNC:
             return  # async call, don't send a response yet
         else:
             data, compressed=self.serializer.serialize(data, compress=Pyro4.config.COMPRESSION)
             flags=0
             if compressed:
                 flags |= MessageFactory.FLAGS_COMPRESSED
             if wasBatched:
                 flags |= MessageFactory.FLAGS_BATCH
             msg=MessageFactory.createMessage(MessageFactory.MSG_RESULT, data, flags, seq)
             del data
             conn.send(msg)
     except Exception as ex:
         xt,xv=sys.exc_info()[0:2]
         if xt is not errors.ConnectionClosedError:
             log.debug("Exception occurred while handling request: %r", xv)
             if client_future is not None:
                 # send exception to the client future
                 client_future.set_exception(ex)
             elif not flags & MessageFactory.FLAGS_ONEWAY:
                 # only return the error to the client if it wasn't a oneway call
                 tblines=util.formatTraceback(detailed=Pyro4.config.DETAILED_TRACEBACK)
                 self._sendExceptionResponse(conn, seq, xv, tblines)
         if isCallback or isinstance(xv, (errors.CommunicationError, errors.SecurityError)):
             raise       # re-raise if flagged as callback, communication or security error.