Пример #1
0
def copy_future(future: asyncio.Future, new_future: asyncio.Future = None):
    new_future = new_future or asyncio.Future(loop=future._loop)

    handler = partial(_on_result, new_future=new_future)

    future.add_done_callback(handler)
    return new_future
Пример #2
0
def wrap_exc(f: asyncio.Future, logger):
    def check_exception(f: asyncio.Future):
        if not f.cancelled() and f.exception() is not None:
            logger.error('Exception! {}'.format(f.exception()))

    f.add_done_callback(check_exception)
    return f
Пример #3
0
    def run_until_complete(self, future: asyncio.Future) -> Any:
        self._check_running()

        new_task = False

        if not asyncio.isfuture(future):
            future = asyncio.ensure_future(future, loop=self)

            # We wrapped `future` in a new Task since it was not a Future.
            new_task = True

            # An exception is raised if the new task doesn't complete, so there is no need to log the "destroy
            # pending task" message.
            future._log_destroy_pending = False
        else:
            if _helpers.get_future_loop(future) is not self:
                raise ValueError("Future does not belong to this loop")

        future.add_done_callback(_run_until_complete_cb)
        try:
            self._run_mainloop()
        except:
            if new_task and future.done() and not future.cancelled():
                # The coroutine raised a BaseException. Consume the exception to not log a warning (Future
                # will log a warning if its exception is not retrieved), the caller doesn't have access to the
                # task wrapper we made.
                future.exception()
            raise
        finally:
            future.remove_done_callback(_run_until_complete_cb)

        if not future.done():
            raise RuntimeError('Event loop stopped before Future completed.')

        return future.result()
Пример #4
0
    def start_tls(self, server_side, ssl_options=None, server_hostname=None, connect_timeout=None):
        if not self._transport or self._read_future:
            raise ValueError("IOStream is not idle; cannot convert to SSL")

        self._connect_ssl_future = connect_ssl_future = Future(loop=self._loop)
        waiter = Future(loop=self._loop)

        def on_connected(future):
            if self._loop_connect_timeout:
                self._loop_connect_timeout.cancel()
                self._loop_connect_timeout = None

            if connect_ssl_future._exception is not None:
                self.on_closed(future.exception())
                self._connect_ssl_future = None
            else:
                self._connect_ssl_future = None
                connect_ssl_future.set_result(self)
        waiter.add_done_callback(on_connected)

        if connect_timeout:
            def on_timeout():
                self._loop_connect_timeout = None
                if not waiter.done():
                    self.close((None, IOError("Connect timeout"), None))

            self._loop_connect_timeout = self._loop.call_later(connect_timeout, on_timeout)

        self._transport.pause_reading()
        sock, self._transport._sock = self._transport._sock, None
        self._transport = self._loop._make_ssl_transport(
            sock, self, ssl_options, waiter,
            server_side=False, server_hostname=server_hostname)

        return connect_ssl_future
Пример #5
0
    def start_tls(self, server_side, ssl_options=None, server_hostname=None, connect_timeout=None):
        if not self._transport or self._read_future:
            raise ValueError("IOStream is not idle; cannot convert to SSL")

        self._connect_ssl_future = connect_ssl_future = Future(loop=self._loop)
        waiter = Future(loop=self._loop)

        def on_connected(future):
            if self._loop_connect_timeout:
                self._loop_connect_timeout.cancel()
                self._loop_connect_timeout = None

            if connect_ssl_future._exception is not None:
                self.on_closed(future.exception())
                self._connect_ssl_future = None
            else:
                self._connect_ssl_future = None
                connect_ssl_future.set_result(self)
        waiter.add_done_callback(on_connected)

        if connect_timeout:
            def on_timeout():
                self._loop_connect_timeout = None
                if not waiter.done():
                    self.close((None, IOError("Connect timeout"), None))

            self._loop_connect_timeout = self._loop.call_later(connect_timeout, on_timeout)

        self._transport.pause_reading()
        sock, self._transport._sock = self._transport._sock, None
        self._transport = self._loop._make_ssl_transport(
            sock, self, ssl_options, waiter,
            server_side=False, server_hostname=server_hostname)

        return connect_ssl_future
Пример #6
0
    async def _waiter(cls, future: asyncio.Future) -> T_Result:
        wait_future = asyncio.Future()  # type: asyncio.Future

        future.add_done_callback(
            partial(cls._set_wait_future_result, wait_future=wait_future))

        return await wait_future
Пример #7
0
def unpack_future(src: asyncio.Future, num_items: int) -> List[asyncio.Future]:
    """Unpack the result of source future to num_items futures.

    This function takes in a Future and splits its result into many futures. If
    the result of the source future is an exception, then all destination
    futures will have the same exception.
    """
    dest_futures = [
        asyncio.get_event_loop().create_future() for _ in range(num_items)
    ]

    def unwrap_callback(fut: asyncio.Future):
        exception = fut.exception()
        if exception is not None:
            [f.set_exception(exception) for f in dest_futures]
            return

        result = fut.result()
        assert len(result) == num_items
        for item, future in zip(result, dest_futures):
            future.set_result(item)

    src.add_done_callback(unwrap_callback)

    return dest_futures
Пример #8
0
    def queue_request(self, aRequest):
        if aRequest not in self._request_queue:
            future = Future()

            future.add_done_callback(functools.partial(self.cleanup_future, aRequest=aRequest))
            self._request_queue[aRequest] = future

        return self._request_queue[aRequest]
Пример #9
0
def propagate(from_: Future, to: Future) -> None:
    """
    Copy the value that ``from_`` is completed with to ``to``, whenever ``from_`` is completed.
    """
    if from_.done():
        copy_result(from_, to)
    else:
        from_.add_done_callback(lambda _: copy_result(from_, to))
Пример #10
0
 def addFuture(self, future: Future, caller, iomode: str):
   def onComplete(fut):
     try:
       # self.future.discard(fut)
       # logger.debug(f"discarding {self.name} {iomode} future")
       self.future = None
       fut.result()
     except asyncio.CancelledError:
       logger.info(f"{caller} {iomode} was cancelled")
     except Exception as ex:
       logger.warn(f"{caller} {iomode} errored : {ex}")
   future.add_done_callback(onComplete)
   self.future = future
Пример #11
0
def copy_future(future: asyncio.Future, new_future: asyncio.Future = None):
    """ Creates a copy of passed future instance. Actually another future will be
    created but result or exception of original future will be passed to created future.

    :param future: :class:`asyncio.Future` instance
    :param new_future: Target future (:class:`None` by default)
    :return: :class:`asyncio.Future`
    """
    new_future = new_future or create_future(loop=future._loop)

    handler = partial(_on_result, new_future=new_future)

    future.add_done_callback(handler)
    return new_future
Пример #12
0
    def assertReactorWorksWithAsyncioFuture(self, reactor):
        """
        Ensure that C{reactor} has an event loop that works
        properly with L{asyncio.Future}.
        """
        future = Future()
        result = []

        def completed(future):
            result.append(future.result())
            reactor.stop()

        future.add_done_callback(completed)
        future.set_result(True)

        self.assertEqual(result, [])
        self.runReactor(reactor, timeout=1)
        self.assertEqual(result, [True])
    def _complete_callback(self,
        result_future: asyncio.Future = None
    ):
        '''
        Obtaining Cloud Function results is complete.
        
        If the acquisition has not started, a coroutine
            acquisition task is created.
        '''

        if not result_future:
            result_future: asyncio.Future = asyncio.run_coroutine_threadsafe(
                self.__function_client.get_function_result_by_request_id_async(
                    region_id = self.__function_metadata['region_id'],
                    namespace_name = self.__function_metadata['namespace_name'],
                    function_name = self.__function_metadata['function_name'],
                    function_request_id = self.__function_request_id,
                    function_version = self.__function_metadata['function_version']
                ),
                self.__function_client.get_event_loop())

            result_future.add_done_callback(self._complete_callback)
        else:
            if result_future.exception():
                if isinstance(result_future.exception(), errors.errors.NotFoundError):
                    self.__function_client.get_event_loop().call_later(1, self._complete_callback)
                else:
                    self.set_exception(result_future.exception())

                return

            function_result: dict = result_future.result()

            if not function_result['is_successful']:
                self.set_exception(errors.InvokeError(
                    error_message = function_result['return_result'],
                    request_id = self.__function_request_id
                ))
            
            self.set_result(helper.inferred_return_result(
                function_result['return_result']))

            self.done()
Пример #14
0
def chain_future(fut: Future, other: Future) -> Future:
    """Chains a future with other future.

    Returns the first future.
    """
    def done(fut):
        if other.done():
            return

        if fut.cancelled():
            other.cancel()
            return

        if fut.exception() is not None:
            other.set_exception(fut.exception())
            return

        other.set_result(fut.result())

    fut.add_done_callback(done)
    return fut
Пример #15
0
    async def set_reader(self, reader: asyncio.Future):
        """
        Cancel the currently running reader and register the new one.
        A reader is a coroutine that calls this transports 'read' function.
        The 'read' function calls can be paused by calling pause_reading of this transport.
        :param reader: future reader
        """
        if self._read_thread is not None:
            # cancel currently running reader
            if self._read_thread.cancel():
                try:
                    await self._read_thread
                except asyncio.CancelledError:
                    pass

        # Create callback for debugging in case the reader is failing
        err_callback = utils.create_error_check_callback(
            ignore=asyncio.CancelledError)
        reader.add_done_callback(err_callback)

        self._read_thread = reader
Пример #16
0
def log_task_exceptions(task: asyncio.Future,
                        logger: Union[logging.Logger,
                                      logging.LoggerAdapter], msg: str):
    """Add a done callback to a task that logs any exception it raised.

    Parameters
    ----------
    task
        Task (or any future) on which the callback will be added
    logger
        Logger to which the warning will be written
    msg
        Message that will be logged
    """
    def done_callback(task):
        if not task.cancelled():
            try:
                task.result()
            except Exception:
                logger.exception('%s', msg)

    task.add_done_callback(done_callback)
Пример #17
0
def aio_future_chain_thread(aio_future: asyncio.Future, future: ThreadFuture):
    """Chain an asyncio future to a thread future.
    If the result of the asyncio future is another aio future this will also
    be chained so the client only sees thread futures
    """
    def done(done_future: asyncio.Future):
        # Here we're on the aio thread
        # Copy over the future
        try:
            result = done_future.result()
            if asyncio.isfuture(result):
                # Change the aio future to a thread future
                fut = ThreadFuture()
                aio_future_chain_thread(result, fut)
                result = fut

            future.set_result(result)
        except asyncio.CancelledError:
            future.cancel()
        except Exception as exception:  # pylint: disable=broad-except
            future.set_exception(exception)

    aio_future.add_done_callback(done)
    return future
Пример #18
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """
    log = txaio.make_logger()

    peer: Optional[str] = None
    is_server: Optional[bool] = None

    def connection_made(self, transport):
        # asyncio networking framework entry point, called by asyncio
        # when the connection is established (either a client or a server)
        self.log.info('{func}(transport={transport})',
                      func=hltype(self.connection_made),
                      transport=transport)

        self.transport = transport

        # determine preliminary transport details (what is know at this point)
        self._transport_details = create_transport_details(
            self.transport, self.is_server)

        # backward compatibility
        self.peer = self._transport_details.peer

        self.receive_queue = deque()
        self._consume()

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        # according to asyncio docs, connection_lost(None) is called
        # if something else called transport.close()
        if exc is not None:
            self.transport.close()
        self.transport = None

    def _consume(self):
        self.waiter = Future(loop=self.factory.loop or txaio.config.loop)

        def process(_):
            while self.receive_queue:
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    def _closeConnection(self, abort=False):
        if abort and hasattr(self.transport, 'abort'):
            self.transport.abort()
        else:
            self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            asyncio.ensure_future(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            asyncio.ensure_future(res)

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")

    def unregisterProducer(self):
        # note that generic websocket/protocol.py code calls
        # .unregisterProducer whenever we dropConnection -- that's
        # correct behavior on Twisted so either we'd have to
        # try/except there, or special-case Twisted, ..or just make
        # this "not an error"
        pass
Пример #19
0
    def add(self, future: asyncio.Future):
        if self.__main_store:
            self.__main_store.add(future)

        self.__collection.add(future)
        future.add_done_callback(self._on_future_done)
async def register_callbacks(all_done: asyncio.Future):
    print("registering callbacks on future")
    all_done.add_done_callback(functools.partial(callback, n=1))
    all_done.add_done_callback(functools.partial(callback, n=2))
Пример #21
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """
    def connection_made(self, transport):
        self.transport = transport

        self.receive_queue = deque()
        self._consume()

        try:
            peer = transport.get_extra_info('peername')
            try:
                # FIXME: tcp4 vs tcp6
                self.peer = u"tcp:%s:%d" % (peer[0], peer[1])
            except:
                # e.g. Unix Domain sockets don't have host/port
                self.peer = u"unix:{0}".format(peer)
        except:
            self.peer = u"?"

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        # according to asyncio docs, connection_lost(None) is called
        # if something else called transport.close()
        if exc is not None:
            self.transport.close()
        self.transport = None

    def _consume(self):
        self.waiter = Future(loop=self.factory.loop or txaio.config.loop)

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    # noinspection PyUnusedLocal
    def _closeConnection(self, abort=False):
        self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            ensure_future(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            ensure_future(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            ensure_future(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            ensure_future(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            ensure_future(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            ensure_future(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            ensure_future(res)

    def get_channel_id(self):
        """
        Implements :func:`autobahn.wamp.interfaces.ITransport.get_channel_id`
        """
        self.log.debug(
            'FIXME: transport channel binding not implemented for asyncio (autobahn-python issue #729)'
        )
        return None

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """

    def connection_made(self, transport):
        self.transport = transport

        self.receive_queue = deque()
        self._consume()

        try:
            peer = transport.get_extra_info('peername')
            try:
                # FIXME: tcp4 vs tcp6
                self.peer = u"tcp:%s:%d" % (peer[0], peer[1])
            except:
                # e.g. Unix Domain sockets don't have host/port
                self.peer = u"unix:{0}".format(peer)
        except:
            self.peer = u"?"

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        # according to asyncio docs, connection_lost(None) is called
        # if something else called transport.close()
        if exc is not None:
            self.transport.close()
        self.transport = None

    def _consume(self):
        self.waiter = Future(loop=self.factory.loop or txaio.config.loop)

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    # noinspection PyUnusedLocal
    def _closeConnection(self, abort=False):
        self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            ensure_future(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            ensure_future(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            ensure_future(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            ensure_future(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            ensure_future(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            ensure_future(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            ensure_future(res)

    def get_channel_id(self):
        """
        Implements :func:`autobahn.wamp.interfaces.ITransport.get_channel_id`
        """
        self.log.debug('FIXME: transport channel binding not implemented for asyncio (autobahn-python issue #729)')
        return None

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")
Пример #23
0
 def cancellable(self):
     def on_done(fut):
         self._cancelled.set_result(fut.cancelled())
     fut = Future(loop=self._lsession.conn.loop)
     fut.add_done_callback(on_done)
     return fut
Пример #24
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """

    peer = None
    peer_transport = None

    def connection_made(self, transport):
        self.transport = transport
        self.receive_queue = deque()
        self._consume()

        # the peer we are connected to
        try:
            self.peer = peer2str(transport.get_extra_info('peername'))
        except:
            self.peer = 'process:{}'.format(self.transport.pid)
        self.peer_transport = 'websocket'

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        # according to asyncio docs, connection_lost(None) is called
        # if something else called transport.close()
        if exc is not None:
            self.transport.close()
        self.transport = None

    def _consume(self):
        self.waiter = Future(loop=self.factory.loop or txaio.config.loop)

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    def _closeConnection(self, abort=False):
        if abort and hasattr(self.transport, 'abort'):
            self.transport.abort()
        else:
            self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            asyncio.ensure_future(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            asyncio.ensure_future(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            asyncio.ensure_future(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            asyncio.ensure_future(res)

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")

    def unregisterProducer(self):
        # note that generic websocket/protocol.py code calls
        # .unregisterProducer whenever we dropConnection -- that's
        # correct behavior on Twisted so either we'd have to
        # try/except there, or special-case Twisted, ..or just make
        # this "not an error"
        pass
Пример #25
0
async def register_callbacks(future: asyncio.Future):
    print('registering callbacks on future')
    future.add_done_callback(functools.partial(callback, n=1))
    future.add_done_callback(functools.partial(callback, n=2))
Пример #26
0
class Lock(object):
    def __init__(self,
                 db,
                 lock_name,
                 timeout=5,
                 expried=8,
                 lock_id=None,
                 max_count=1,
                 reentrant_count=0):
        self._db = db
        self._db_id = db.id
        self._lock_name = lock_name
        self._lock_id = lock_id or self.generate()
        self._timeout = timeout
        self._expried = expried
        self._max_count = max_count
        self._reentrant_count = reentrant_count
        self._lock_future = None
        self._unlock_future = None

    def generate(self):
        return UniqId().to_bytes()

    def acquire(self, flag=0):
        if self._lock_future:
            raise LockIsLockingError(Result(b'\x56\x01' + b'\x00' * 62))

        self._lock_future = Future()
        command = Command(Command.COMMAND_TYPE.LOCK, self._lock_id,
                          self._db_id, self._lock_name, self._timeout,
                          self._expried, flag, max(self._max_count - 1, 0),
                          max(self._reentrant_count - 1, 0))

        def finish(future):
            self._lock_future = None

        self._lock_future.add_done_callback(finish)
        self._db.command(self, command, self._lock_future)
        return self._lock_future

    def release(self, flag=0):
        if self._unlock_future:
            raise LockIsUnlockingError(Result(b'\x56\x01' + b'\x00' * 62))

        self._unlock_future = Future()
        command = Command(Command.COMMAND_TYPE.UNLOCK, self._lock_id,
                          self._db_id, self._lock_name, self._timeout,
                          self._expried, flag, max(self._max_count - 1, 0),
                          max(self._reentrant_count - 1, 0))

        def finish(future):
            self._unlock_future = None

        self._unlock_future.add_done_callback(finish)
        self._db.command(self, command, self._unlock_future)
        return self._unlock_future

    def on_result(self, result):
        if result.command == Command.COMMAND_TYPE.LOCK:
            self.on_lock_result(result)
        elif result.command == Command.COMMAND_TYPE.UNLOCK:
            self.on_unlock_result(result)

    def on_lock_result(self, result):
        if result.result == RESULT_SUCCED:
            self._lock_future.set_result(result)
        else:
            if result.result in ERRORS:
                e = ERRORS[result.result](result)
            else:
                e = LockException(result)
            self._lock_future.set_exception(e)

    def on_unlock_result(self, result):
        if result.result == RESULT_SUCCED:
            self._unlock_future.set_result(result)
        else:
            if result.result in ERRORS:
                e = ERRORS[result.result](result)
            else:
                e = LockException(result)
            self._unlock_future.set_exception(e)

    async def __aenter__(self):
        await self.acquire()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.release()
Пример #27
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """

    def connection_made(self, transport):
        self.transport = transport

        self.receive_queue = deque()
        self._consume()

        try:
            peer = transport.get_extra_info('peername')
            try:
                # FIXME: tcp4 vs tcp6
                self.peer = "tcp:%s:%d" % (peer[0], peer[1])
            except:
                # e.g. Unix Domain sockets don't have host/port
                self.peer = "unix:{0}".format(peer)
        except:
            self.peer = "?"

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        self.transport = None

    def _consume(self):
        self.waiter = Future()

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
                else:
                    print("WebSocketAdapterProtocol._consume: no transport")
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    # noinspection PyUnusedLocal
    def _closeConnection(self, abort=False):
        self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            asyncio.async(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            asyncio.async(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            asyncio.async(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            asyncio.async(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            asyncio.async(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            asyncio.async(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            asyncio.async(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            asyncio.async(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            asyncio.async(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            asyncio.async(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            asyncio.async(res)

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")
Пример #28
0
    await asyncsleep(0.1)
    future_.set_result('\n\tFuture completed.')


def got(future_):
    print(future_.result())
    loop.stop()


loop = get_event_loop()  # get the current event loop
future = Future()  # promise of a result

ensure_future(
    slow(future)
)  # wrap a coroutine or an awaitable in a future (if the arg is a future, return it directly)
future.add_done_callback(got)  # add callback for Future

try:
    loop.run_forever()
finally:
    loop.close()


async def speller():
    for letter in '\tHI!':
        await asyncsleep(0.25)
        print(letter, end='')


run(speller())
print()
Пример #29
0
 def prepare(self, future: asyncio.Future, default: Any, pack_single: bool) -> Callable[..., None]:
     on_ready = functools.partial(self._on_ready, future=future, default=default, pack_single=pack_single)
     future.add_done_callback(lambda _future: self._ready_callbacks.discard(on_ready))
     self._ready_callbacks.add(on_ready)
     return on_ready
Пример #30
0
class _Application(Tk):
    '''Ringmaster main application window.'''

    def __init__(self, parent=None):
        super().__init__(parent)

        # Internal.
        self._sub = self._req1 = self._rep1 = self._req2 = self._rep2 = None
        self._running = True
        self._toplevel = None

        # GUI.
        self._font = font.Font(family='Helvetica', size=12)  # See [A1].
        self._master = ttk.Frame(self, name='master', padding=(10, 10, 10, 10))
        self._title = ttk.Label(self._master, text='Watchers', font='-size 16')
        self._frame = ttk.Frame(self._master, name='frame')
        self._button = ttk.Button(self._master, text='Quit')
        self._grid = self._frame.children

        self.createcommand('::tk::mac::Quit', self._quit)  # See [A2].
        self.resizable(False, False)
        self.minsize(320, 160)
        self.title(_TITLE)

        self._master.grid(row=0, column=0, sticky='NSEW')
        self._title.grid(row=0, column=0, pady=(0, 10))
        self._frame.grid(row=1, column=0, sticky='EW')
        self._button.grid(row=2, column=0, sticky='EW', pady=(10, 0))

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self._master.columnconfigure(0, weight=1)
        self._frame.columnconfigure(0, weight=1)

        self._button.bind('<Button-1>', lambda x: self._quit())

    @coroutine
    def setup(self):
        factory1 = lambda: _CircusSubProtocol(self)
        factory2 = lambda: _CircusDealerProtocol(self, '_rep1')
        factory3 = lambda: _CircusDealerProtocol(self, '_rep2')

        self._sub, __ = yield from create_zmq_connection(factory1, SUB)
        self._req1, _ = yield from create_zmq_connection(factory2, DEALER)
        self._req2, _ = yield from create_zmq_connection(factory3, DEALER)

        self._sub.subscribe(b'')
        self._sub.connect(_CIRCUS_STATS_ADDR)

        self._req1.setsockopt(LINGER, 0)
        self._req1.setsockopt(IDENTITY, uuid4().hex.encode())
        self._req1.connect(_CIRCUS_CONTROL_ADDR)

        self._req2.setsockopt(LINGER, 0)
        self._req2.setsockopt(IDENTITY, uuid4().hex.encode())
        self._req2.connect(_CIRCUS_CONTROL_ADDR)

    @coroutine
    def paint(self):
        set1 = set((yield from self._do_request('list')).get('watchers', []))
        set2 = set()
        set3 = set()

        ttk.Style().map('TLabel', foreground=[('disabled', 'gray')])  # [A3].
        ttk.Style().map('TButton', foreground=[('disabled', 'gray')])

        # Pass one, classify watchers: all, singletons and forgotten.
        for watcher in set1:
            conf = yield from self._do_request('options', watcher)

            if conf['options']['singleton']:
                set2.add(watcher)

            if 'forget' in conf['options']:
                set3.update(conf['options']['forget'].split())

        # Pass two, assemble the watcher grid.
        for i, name in enumerate(sorted(set1 - set3)):
            lb1 = ttk.Label(self._frame, name=name + '+l', text=_DOT(name))
            lb2 = ttk.Label(self._frame, name=name + '+c1', text='–')

            lb1.grid(row=i, column=0, sticky='EW')
            lb2.grid(row=i, column=1)

            lb2.config(anchor='center', width=25, foreground='grey')

            if name in set2:
                bt1 = ttk.Button(self._frame, name=name + '+c2', text='Start')
                bt2 = ttk.Button(self._frame, name=name + '+r', text=' +')

                bt1.grid(row=i, column=2, columnspan=2, sticky='EW')
                bt2.grid(row=i, column=4)

                bt1.bind('<Button-1>', partial(self._start_watcher, name))
                bt2.config(state='disabled', width=3)

            else:
                bt1 = ttk.Button(self._frame, name=name + '+c2', text='Incr')
                bt2 = ttk.Button(self._frame, name=name + '+c3', text='Decr')
                bt3 = ttk.Button(self._frame, name=name + '+r', text=' +')

                bt1.grid(row=i, column=2)
                bt2.grid(row=i, column=3)
                bt3.grid(row=i, column=4)

                bt1.bind('<Button-1>', partial(self._incr_process, name))
                bt2.config(state='disabled')
                bt3.config(state='disabled', width=3)

            # Put metadata in label one.
            lb1._w_procs = []
            lb1._w_state = 'stopped'
            lb1._w_singleton = name in set2

        # Pass three, continuously update watcher state.
        while self._running:
            for name in set1 - set3:
                state = yield from self._do_request('status', name)
                stats = yield from self._do_request('stats', name)
                procs = list(stats.get('info', {}).keys())
                label = self._grid[name + '+l']

                label._w_state = state

                if sorted(label._w_procs) != sorted(procs):  # See [LEAK2].
                    label._w_procs = [int(x) for x in procs]

                    self._update_watcher_state_a(name)

            yield from sleep(0.5)

    # Taken from "http://www.reddit.com/r/Python/comments/33ecpl".
    #
    # For a threaded approach, see the ActiveState recipe mentioned by Guido
    # van Rossum at the "Tkinter-discuss" list ("http://goo.gl/VJI1oJ").
    #
    @coroutine
    def mainloop(self, interval=0.05):
        '''Run a tkinter app in an asyncio event loop.'''

        try:
            while self._running:
                self.update()

                yield from sleep(interval)

        except TclError as e:
            if 'application has been destroyed' not in e.args[0]:
                raise

    # This method:
    #
    #   1. Is a standard coroutine. Cannot run concurrently, otherwise a
    #      second request may happen before a reply arrives. It is called
    #      only from "_paint, so concurrency is not an issue. But be
    #      aware when calling this method from other methods or functions.
    #
    #   2. Writes to socket "_req1". This is a REQ/REP socket that will only
    #      receive monitoring commands.
    #
    #   3. Does not return error messages. Monitoring commands are passive,
    #      automatically issued by the program. A fail can simply be discarded,
    #      and the GUI updates that would arise from it, bypassed. A common
    #      error is caused by the process stopping while Circus is executing a
    #      command on it, like "stats".
    #
    @coroutine
    def _do_request(self, action, name=''):
        query = {'id': uuid4().hex, 'command': action}
        reply = {}

        if name:
            query['properties'] = {'name': name}

        self._rep1 = Future()

        self._req1.write([dumps(query).encode()])

        reply = yield from self._rep1

        if query['id'] == reply['id'] and action == 'status':
            return reply['status']

        elif query['id'] == reply['id'] and reply['status'] == 'ok':
            return reply

        elif query['id'] == reply['id']:
            return {}

        else:
            raise Exception()

    # This method:
    #
    #   1. Is a coroutine, mostly because it needs to block to prevent that
    #      more than one request is written on the REQ/REP socket before a
    #      reply arrives. It can run concurrently, and often will, since it
    #      will be spawned from event handlers attached to buttons and other
    #      GUI widgets. That is also why it adopts a callback approach to
    #      provide a reply. Tkinter event handlers cannot yield on the result
    #      of a coroutine.
    #
    #   2. Writes to socker "_req2". This socket should be used to send
    #      management commands to wachers, like stop, increment a process etc.
    #
    #   3. Returns error messages. Here, actions sent to Circus come from
    #      direct interaction with the GUI, and errors messages are expected.
    #
    @coroutine
    def _on_reply(self, action, name, on_reply_ok, on_reply_error):
        def callback(future):
            reply = future.result()

            if query['id'] == reply['id'] and reply['status'] == 'ok':
                on_reply_ok(reply)

            elif query['id'] == reply['id']:
                on_reply_error(reply['reason'].capitalize() + '.')

            else:
                raise Exception()

        query = {'id': uuid4().hex, 'command': action}

        query['properties'] = {'name': name}

        if action == 'incr' or action == 'decr':
            query['properties'].update({'waiting': False, 'nb': 1})

        elif action == 'start' or action == 'stop':
            query['properties'].update({'waiting': False, 'match': 'glob'})

        # Block to prevent writing multiple requests before reading a reply.
        if self._rep2:
            yield from self._rep2

        self._rep2 = Future()

        self._rep2.add_done_callback(callback)

        self._req2.write([dumps(query).encode()])

    def _update_watcher_state_a(self, name):  # See [LEAK].
        lb1 = self._grid[name + '+l']
        lb2 = self._grid[name + '+c1']

        if lb1._w_singleton:
            bt1 = self._grid[name + '+c2']
            bt2 = self._grid[name + '+r']

            if lb1._w_procs:
                lb2.config(foreground='darkgreen')
                bt1.config(text='Stop')
                bt2.config(state='normal')

                bt1.bind('<Button-1>', partial(self._stop_watcher, name))
                bt2.bind('<Button-1>', partial(self._more_watcher, name))

            else:
                lb2.config(foreground='grey', text='–')
                bt1.config(text='Start')
                bt2.config(state='disabled')

                bt1.bind('<Button-1>', partial(self._start_watcher, name))
                bt2.unbind('<Button-1>')

        else:
            bt1 = self._grid[name + '+c2']
            bt2 = self._grid[name + '+c3']
            bt3 = self._grid[name + '+r']

            if lb1._w_procs:
                lb2.config(foreground='darkgreen')
                bt2.config(state='normal')
                bt3.config(state='normal')

                bt1.bind('<Button-1>', partial(self._incr_process, name))
                bt2.bind('<Button-1>', partial(self._decr_process, name))
                bt3.bind('<Button-1>', partial(self._more_watcher, name))

            else:
                lb2.config(foreground='grey', text='–')
                bt2.config(state='disabled')
                bt3.config(state='disabled')

                bt1.bind('<Button-1>', partial(self._incr_process, name))
                bt2.unbind('<Button-1>')
                bt3.unbind('<Button-1>')

    def _update_watcher_state_b(self, watcher, stats):  # See [LEAK].
        if watcher + '+l' in self._grid and 'pid' in stats:
            lb1 = self._grid[watcher + '+l']

            lb1._w_procs = [int(x) for x in stats['pid']]

            if stats['pid']:
                lb2 = self._frame.children[watcher + '+c1']
                tpl = '{}: {cpu:.1%} cpu, {mem:.1%} mem'

                if stats['cpu'] == 'N/A':
                    stats['cpu'] = 0

                else:
                    stats['cpu'] /= 100.0

                if stats['mem'] == 'N/A':
                    stats['mem'] = 0

                else:
                    stats['mem'] /= 100.0

                # http://docs.python.org/3/library/string.html#format-examples.
                lb2.config(text=tpl.format(len(stats['pid']), **stats))

            if self._toplevel:
                self._toplevel._painter.send(None)

    def _start_watcher(self, name, event):
        def ok(reply):
            lbl._w_procs.append(0)  # Request actual PIDs here (FIXME).

            self._update_watcher_state_a(name)

        def error(message):
            btn.bind('<Button-1>', partial(self._start_watcher, name))

            messagebox.showerror('Error', message + '.')

        lbl = self._grid[name + '+l']
        btn = self._grid[name + '+c2']

        btn.unbind('<Button-1>')

        async(self._on_reply('start', name, ok, error))

    def _stop_watcher(self, name, event):
        def ok(reply):
            lbl._w_procs.pop()  # Request actual PIDs here (FIXME).

            self._update_watcher_state_a(name)

        def error(message):
            btn.bind('<Button-1>', partial(self._start_watcher, name))

            messagebox.showerror('Error', message + '.')

        lbl = self._frame.children[name + '+l']
        btn = self._frame.children[name + '+c2']

        btn.unbind('<Button-1>')

        async(self._on_reply('stop', name, ok, error))

    def _more_watcher(self, name, event):
        self._toplevel = _Dialog(self, name)

    def _incr_process(self, watcher, event):
        def ok1(reply):
            lbl._w_procs.append(0)  # Request actual PIDs here (FIXME).
            lbl._w_state = 'active'

            self._update_watcher_state_a(watcher)

        def ok2(reply):
            lbl._w_procs.append(0)  # Request actual PIDs here (FIXME).

            self._update_watcher_state_a(watcher)

        def error(message):
            btn.bind('<Button-1>', partial(self._incr_process, watcher))

            messagebox.showerror('Error', message + '.')

        lbl = self._grid[watcher + '+l']
        btn = self._grid[watcher + '+c2']

        btn.unbind('<Button-1>')

        if lbl._w_state == 'stopped':
            async(self._on_reply('start', watcher, ok1, error))

        else:
            async(self._on_reply('incr', watcher, ok2, error))

    def _decr_process(self, watcher, event):
        def ok(reply):
            lbl._w_procs.pop()  # Request actual PIDs here (FIXME).

            self._update_watcher_state_a(watcher)

        def error(message):
            btn.bind('<Button-1>', partial(self._decr_process, watcher))

            messagebox.showerror('Error', message + '.')

        lbl = self._grid[watcher + '+l']
        btn = self._grid[watcher + '+c3']

        btn.unbind('<Button-1>')

        async(self._on_reply('decr', watcher, ok, error))

    def _quit(self):
        self._running = False
Пример #31
0
 def _add_cleanup(self, task: asyncio.Future) -> None:
     self._cleanups.add(task)
     task.add_done_callback(log_exception)
     task.add_done_callback(self._cleanups.discard)
Пример #32
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """
    def connection_made(self, transport):
        self.transport = transport

        self.receive_queue = deque()
        self._consume()

        try:
            peer = transport.get_extra_info('peername')
            try:
                # FIXME: tcp4 vs tcp6
                self.peer = "tcp:%s:%d" % (peer[0], peer[1])
            except:
                # e.g. Unix Domain sockets don't have host/port
                self.peer = "unix:{0}".format(peer)
        except:
            self.peer = "?"

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        self.transport = None

    def _consume(self):
        self.waiter = Future()

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
                else:
                    print("WebSocketAdapterProtocol._consume: no transport")
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    # noinspection PyUnusedLocal
    def _closeConnection(self, abort=False):
        self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            asyncio. async (res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            asyncio. async (res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            asyncio. async (res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            asyncio. async (res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            asyncio. async (res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            asyncio. async (res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            asyncio. async (res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            asyncio. async (res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            asyncio. async (res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            asyncio. async (res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            asyncio. async (res)

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")
Пример #33
0
class WebSocketAdapterProtocol(asyncio.Protocol):
    """
    Adapter class for asyncio-based WebSocket client and server protocols.
    """

    def connection_made(self, transport):
        self.transport = transport

        self.receive_queue = deque()
        self._consume()

        try:
            self.peer = peer2str(transport.get_extra_info('peername'))
        except:
            self.peer = u"?"

        self._connectionMade()

    def connection_lost(self, exc):
        self._connectionLost(exc)
        # according to asyncio docs, connection_lost(None) is called
        # if something else called transport.close()
        if exc is not None:
            self.transport.close()
        self.transport = None

    def _consume(self):
        self.waiter = Future(loop=self.factory.loop or txaio.config.loop)

        def process(_):
            while len(self.receive_queue):
                data = self.receive_queue.popleft()
                if self.transport:
                    self._dataReceived(data)
            self._consume()

        self.waiter.add_done_callback(process)

    def data_received(self, data):
        self.receive_queue.append(data)
        if not self.waiter.done():
            self.waiter.set_result(None)

    def _closeConnection(self, abort=False):
        if abort and hasattr(self.transport, 'abort'):
            self.transport.abort()
        else:
            self.transport.close()

    def _onOpen(self):
        res = self.onOpen()
        if yields(res):
            ensure_future(res)

    def _onMessageBegin(self, isBinary):
        res = self.onMessageBegin(isBinary)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameBegin(self, length):
        res = self.onMessageFrameBegin(length)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameData(self, payload):
        res = self.onMessageFrameData(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageFrameEnd(self):
        res = self.onMessageFrameEnd()
        if yields(res):
            ensure_future(res)

    def _onMessageFrame(self, payload):
        res = self.onMessageFrame(payload)
        if yields(res):
            ensure_future(res)

    def _onMessageEnd(self):
        res = self.onMessageEnd()
        if yields(res):
            ensure_future(res)

    def _onMessage(self, payload, isBinary):
        res = self.onMessage(payload, isBinary)
        if yields(res):
            ensure_future(res)

    def _onPing(self, payload):
        res = self.onPing(payload)
        if yields(res):
            ensure_future(res)

    def _onPong(self, payload):
        res = self.onPong(payload)
        if yields(res):
            ensure_future(res)

    def _onClose(self, wasClean, code, reason):
        res = self.onClose(wasClean, code, reason)
        if yields(res):
            ensure_future(res)

    def registerProducer(self, producer, streaming):
        raise Exception("not implemented")

    def unregisterProducer(self):
        # note that generic websocket/protocol.py code calls
        # .unregisterProducer whenever we dropConnection -- that's
        # correct behavior on Twisted so either we'd have to
        # try/except there, or special-case Twisted, ..or just make
        # this "not an error"
        pass