def register(self, obj, objectId=None): """ Register a Pyro object under the given id. Note that this object is now only known inside this daemon, it is not automatically available in a name server. This method returns a URI for the registered object. """ if objectId: if not isinstance(objectId, basestring): raise TypeError("objectId must be a string or None") else: objectId = "obj_" + uuid.uuid4().hex # generate a new objectId if hasattr( obj, "_pyroId" ) and obj._pyroId != "": # check for empty string is needed for Cython raise errors.DaemonError("object already has a Pyro id") if objectId in self.objectsById: raise errors.DaemonError("object already registered with that id") # set some pyro attributes obj._pyroId = objectId obj._pyroDaemon = self if Pyro4.config.AUTOPROXY: # register a custom serializer for the type to automatically return proxies # we need to do this for all known serializers for ser in util._serializers.values(): ser.register_type_replacement(type(obj), pyroObjectToAutoProxy) # register the object in the mapping self.objectsById[obj._pyroId] = obj return self.uriFor(objectId)
def register(self, obj, objectId=None): """ Register a Pyro object under the given id. Note that this object is now only known inside this daemon, it is not automatically available in a name server. This method returns a URI for the registered object. """ if objectId: if not isinstance(objectId, basestring): raise TypeError("objectId must be a string or None") else: objectId="obj_"+uuid.uuid4().hex # generate a new objectId if hasattr(obj, "_pyroId") and obj._pyroId != "": # check for empty string is needed for Cython raise errors.DaemonError("object already has a Pyro id") if objectId in self.objectsById: raise errors.DaemonError("object already registered with that id") # set some pyro attributes obj._pyroId=objectId obj._pyroDaemon=self if Pyro4.config.AUTOPROXY: # register a custom serializer for the type to automatically return proxies try: if isinstance(obj, tuple(self.serializers)): # Find the most fitting serializer by picking the highest in the mro for t in type(obj).__mro__: if t in self.serializers: copyreg.pickle(type(obj), self.serializers[t]) break else: copyreg.pickle(type(obj),pyroObjectSerializer) except TypeError: pass # register the object in the mapping self.objectsById[obj._pyroId]=obj return self.uriFor(objectId)
def get_metadata(objectId): obj = self.objectsById.get(objectId) if obj is not None: if hasattr(obj, 'QSUB_metadata'): return getattr(obj, 'QSUB_metadata') return pyro_util.get_exposed_members(obj, only_exposed=Pyro4.config.REQUIRE_EXPOSE) else: Pyro4.core.log.debug("unknown object requested: %s", objectId) raise pyro_errors.DaemonError("unknown object")
def uriFor(self, objectOrId=None, nat=True): """ Get a URI for the given object (or object id) from this daemon. Only a daemon can hand out proper uris because the access location is contained in them. Note that unregistered objects cannot be given an uri, but unregistered object names can (it's just a string we're creating in that case). If nat is set to False, the configured NAT address (if any) is ignored and it will return an URI for the internal address. """ if not isinstance(objectOrId, basestring): objectOrId = getattr(objectOrId, "_pyroId", None) if objectOrId is None: raise errors.DaemonError("object isn't registered") if nat: loc = self.natLocationStr or self.locationStr else: loc = self.locationStr return URI("PYRO:%s@%s" % (objectOrId, loc))
def unregister(self, objectOrId): """ Remove an object from the known objects inside this daemon. You can unregister an object directly or with its id. """ if objectOrId is None: raise ValueError("object or objectid argument expected") if not isinstance(objectOrId, basestring): objectId = getattr(objectOrId, "_pyroId", None) if objectId is None: raise errors.DaemonError("object isn't registered") else: objectId = objectOrId objectOrId = None if objectId == constants.DAEMON_NAME: return if objectId in self.objectsById: del self.objectsById[objectId] if objectOrId is not None: del objectOrId._pyroId del objectOrId._pyroDaemon
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.
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.