class Values(object): # helper to collect multiple values; ignore errors unless nothing has succeeded # QQQ could probably be moved somewhere - hub.py? __slots__ = ['count', 'values', 'error', 'waiter'] def __init__(self, hub, count): self.count = count self.values = [] self.error = None self.waiter = Waiter(hub) def __call__(self, source): self.count -= 1 if source.exception is None: self.values.append(source.value) else: self.error = source.exception if self.count <= 0: self.waiter.switch() def get(self): self.waiter.get() if self.values: return self.values else: raise self.error
def kill(self, exception=GreenletExit, block=True, timeout=None): """Raise the ``exception`` in the greenlet. If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires. If block is ``False``, the current greenlet is not unscheduled. The function always returns ``None`` and never raises an error. .. note:: Depending on what this greenlet is executing and the state of the event loop, the exception may or may not be raised immediately when this greenlet resumes execution. It may be raised an a subsequent green call, or, if this greenlet exits before making such a call, it may not be raised at all. As of 1.1, an example where the exception is raised later is if this greenlet had called ``sleep(0)``; an example where the exception is raised immediately is if this greenlet had called ``sleep(0.1)``. See also :func:`gevent.kill`. .. versionchanged:: 0.13.0 *block* is now ``True`` by default. """ # XXX this function should not switch out if greenlet is not started but it does # XXX fix it (will have to override 'dead' property of greenlet.greenlet) if self._start_event is None: self._start_event = _dummy_event else: self._start_event.stop() if not self.dead: waiter = Waiter() self.parent.loop.run_callback(_kill, self, exception, waiter) if block: waiter.get() self.join(timeout)
class Values(object): # helper to collect multiple values; ignore errors unless nothing has succeeded # QQQ could probably be moved somewhere - hub.py? __slots__ = ["count", "values", "error", "waiter"] def __init__(self, hub, count): self.count = count self.values = [] self.error = None self.waiter = Waiter(hub) def __call__(self, source): self.count -= 1 if source.exception is None: self.values.append(source.value) else: self.error = source.exception if self.count <= 0: self.waiter.switch() def get(self): self.waiter.get() if self.values: return self.values else: assert error is not None raise self.error # pylint:disable=raising-bad-type
def _http_request(self, **kwargs): res = super(Bucket, self)._http_request(**kwargs) w = Waiter() res.callback = lambda x: w.switch(x) res.errback = lambda x, c, o, b: w.throw(c, o, b) return w.get()
def _gethostbyaddr(self, ip_address): if PY3: if isinstance(ip_address, str): ip_address = ip_address.encode("idna") elif not isinstance(ip_address, (bytes, bytearray)): raise TypeError("Expected es(idna), not %s" % type(ip_address).__name__) else: if isinstance(ip_address, text_type): ip_address = ip_address.encode("ascii") elif not isinstance(ip_address, str): raise TypeError("Expected string, not %s" % type(ip_address).__name__) waiter = Waiter(self.hub) try: self.ares.gethostbyaddr(waiter, ip_address) return waiter.get() except InvalidIP: result = self._getaddrinfo(ip_address, None, family=AF_UNSPEC, socktype=SOCK_DGRAM) if not result: raise _ip_address = result[0][-1][0] if isinstance(_ip_address, text_type): _ip_address = _ip_address.encode("ascii") if _ip_address == ip_address: raise waiter.clear() self.ares.gethostbyaddr(waiter, _ip_address) return waiter.get()
def _wait(self, action=None, timeout=None): """ 等待本service_name下的service变更 :param timeout: :type timeout: float :return: """ remain = timeout waiter = Waiter() self._oc.add_waiter(self.service_name, waiter) try: while True: with Timeout(remain, _TimeOut): start = time.time() cur_action = waiter.get() remain = remain - (time.time() - start) if action is None: # 没有特别指明需要的动作 break elif action == cur_action: # 捕获到需要的动作 break elif remain < 0.001: # 剩余超时时间不足1ms raise _TimeOut else: continue except _TimeOut: # 发生超时 return False except Exception as e: raise err.OctpParamError('catch unexpect error: %s. more: %s', e, traceback.format_exc()) else: return True finally: self._oc.del_waiter(self.service_name, waiter)
def __getnameinfo(self, hostname, port, sockaddr, flags): result = self.__getaddrinfo(hostname, port, family=AF_UNSPEC, socktype=SOCK_DGRAM, proto=0, flags=0, fill_in_type_proto=False) if len(result) != 1: raise error('sockaddr resolved to multiple addresses') family, _socktype, _proto, _name, address = result[0] if family == AF_INET: if len(sockaddr) != 2: raise error("IPv4 sockaddr must be 2 tuple") elif family == AF_INET6: address = address[:2] + sockaddr[2:] waiter = Waiter(self.hub) self.cares.getnameinfo(waiter, address, flags) node, service = waiter.get() if service is None and PY3: # ares docs: "If the query did not complete # successfully, or one of the values was not # requested, node or service will be NULL ". Python 2 # allows that for the service, but Python 3 raises # an error. This is tested by test_socket in py 3.4 err = gaierror(EAI_NONAME, self.EAI_NONAME_MSG) err.errno = EAI_NONAME raise err return node, service or '0'
class Values(object): # helper to collect multiple values; ignore errors unless nothing has succeeded # QQQ could probably be moved somewhere - hub.py? __slots__ = ['count', 'values', 'error', 'waiter'] def __init__(self, hub, count): self.count = count self.values = [] self.error = None self.waiter = Waiter(hub) def __call__(self, source): self.count -= 1 if source.exception is None: self.values.append(source.value) else: self.error = source.exception if self.count <= 0: self.waiter.switch() def get(self): self.waiter.get() if self.values: return self.values else: assert error is not None raise self.error # pylint:disable=raising-bad-type
def peek(self, block=True, timeout=None): if self.qsize(): if self.putters: self._schedule_unlock() return self._peek() elif not block and get_hub() is getcurrent(): # special case to make peek(False) runnable in the mainloop # greenlet there are no items in the queue; try to fix the # situation by unlocking putters while self.putters: putter = self.putters.pop() if putter: putter.switch(putter) if self.qsize(): return self._peek() raise Empty elif block: waiter = Waiter() timeout = Timeout.start_new(timeout, Empty) try: self.getters.add(waiter) if self.putters: self._schedule_unlock() result = waiter.get() assert result is waiter, "Invalid switch into Queue.put: %r" % (result,) return self._peek() finally: self.getters.discard(waiter) timeout.cancel() else: raise Empty
def peek(self, block=True, timeout=None): """Return an item from the queue without removing it. If optional args *block* is true and *timeout* is ``None`` (the default), block if necessary until an item is available. If *timeout* is a positive number, it blocks at most *timeout* seconds and raises the :class:`Empty` exception if no item was available within that time. Otherwise (*block* is false), return an item if one is immediately available, else raise the :class:`Empty` exception (*timeout* is ignored in that case). """ if self.qsize(): return self._peek() elif self.hub is getcurrent(): # special case to make peek(False) runnable in the mainloop greenlet # there are no items in the queue; try to fix the situation by unlocking putters while self.putters: self.putters.pop().put_and_switch() if self.qsize(): return self._peek() raise Empty elif block: waiter = Waiter() timeout = Timeout.start_new(timeout, Empty) try: self.getters.add(waiter) if self.putters: self._schedule_unlock() result = waiter.get() assert result is waiter, 'Invalid switch into Queue.peek: %r' % (result, ) return self._peek() finally: self.getters.discard(waiter) timeout.cancel() else: raise Empty
def _getnameinfo(self, sockaddr, flags): if not isinstance(flags, int): raise TypeError('an integer is required') if not isinstance(sockaddr, tuple): raise TypeError('getnameinfo() argument 1 must be a tuple') waiter = Waiter(self.hub) result = self._getaddrinfo(sockaddr[0], str(sockaddr[1]), family=AF_UNSPEC, socktype=SOCK_DGRAM) if not result: raise elif len(result) != 1: raise error('sockaddr resolved to multiple addresses') family, socktype, proto, name, address = result[0] if family == AF_INET: if len(sockaddr) != 2: raise error("IPv4 sockaddr must be 2 tuple") elif family == AF_INET6: address = address[:2] + sockaddr[2:] self.ares.getnameinfo(waiter, address, flags) node, service = waiter.get() if service is None: service = '0' return node, service
def gethostbyname_ex(self, hostname, family=AF_INET): if PY3: if isinstance(hostname, str): hostname = hostname.encode('idna') elif not isinstance(hostname, (bytes, bytearray)): raise TypeError('Expected es(idna), not %s' % type(hostname).__name__) else: if isinstance(hostname, text_type): hostname = hostname.encode('ascii') elif not isinstance(hostname, str): raise TypeError('Expected string, not %s' % type(hostname).__name__) while True: ares = self.ares try: waiter = Waiter(self.hub) ares.gethostbyname(waiter, hostname, family) result = waiter.get() if not result[-1]: raise gaierror(-5, 'No address associated with hostname') return result except gaierror: if ares is self.ares: if hostname == b'255.255.255.255': # The stdlib handles this case in 2.7 and 3.x, but ares does not. # It is tested by test_socket.py in 3.4. # HACK: So hardcode the expected return. return ('255.255.255.255', [], ['255.255.255.255']) raise
def put(self, item, block=True, timeout=None): if self.hub is getcurrent(): if self.getters: getter = self.getters.popleft() getter.switch(item) return raise Full if not block: timeout = 0 waiter = Waiter() item = (item, waiter) self.putters.append(item) timeout = Timeout.start_new(timeout, Full) try: if self.getters: self._schedule_unlock() result = waiter.get() assert result is waiter, "Invalid switch into Channel.put: %r" % ( result, ) except: self._discard(item) raise finally: timeout.cancel()
def waitany(objects, timeout=None): waiter = Waiter() switch = waiter.switch if not objects: return None timer = None if timeout is not None: timer = core.timer(timeout, switch, _NONE) try: for obj in objects: obj.rawlink(switch) rst = waiter.get() return None if rst is _NONE else rst finally: timer and timer.cancel() for obj in objects: unlink = getattr(obj, 'unlink', None) if unlink: try: unlink(switch) except: import traceback traceback.print_exc()
def peek(self, block=True, timeout=None): if self.qsize(): if self.putters: self._schedule_unlock() return self._peek() elif not block and get_hub() is getcurrent(): # special case to make peek(False) runnable in the mainloop # greenlet there are no items in the queue; try to fix the # situation by unlocking putters while self.putters: putter = self.putters.pop() if putter: putter.switch(putter) if self.qsize(): return self._peek() raise Empty elif block: waiter = Waiter() timeout = Timeout.start_new(timeout, Empty) try: self.getters.add(waiter) if self.putters: self._schedule_unlock() result = waiter.get() assert result is waiter, "Invalid switch into Queue.put: %r" % ( result, ) return self._peek() finally: self.getters.discard(waiter) timeout.cancel() else: raise Empty
def gethostbyname_ex(self, hostname, family=AF_INET): if PY3: if isinstance(hostname, str): hostname = hostname.encode("idna") elif not isinstance(hostname, (bytes, bytearray)): raise TypeError("Expected es(idna), not %s" % type(hostname).__name__) else: if isinstance(hostname, text_type): hostname = hostname.encode("ascii") elif not isinstance(hostname, str): raise TypeError("Expected string, not %s" % type(hostname).__name__) while True: ares = self.ares try: waiter = Waiter(self.hub) ares.gethostbyname(waiter, hostname, family) result = waiter.get() if not result[-1]: raise gaierror(-5, "No address associated with hostname") return result except gaierror: if ares is self.ares: if hostname == b"255.255.255.255": # The stdlib handles this case in 2.7 and 3.x, but ares does not. # It is tested by test_socket.py in 3.4. # HACK: So hardcode the expected return. return ("255.255.255.255", [], ["255.255.255.255"]) raise
def put(self, item, block=True, timeout=None): if self.hub is getcurrent(): if self.getters: getter = self.getters.popleft() getter.switch(item) return raise Full if not block: timeout = 0 waiter = Waiter() item = (item, waiter) self.putters.append(item) timeout = Timeout.start_new(timeout, Full) try: if self.getters: self._schedule_unlock() result = waiter.get() assert result is waiter, "Invalid switch into Channel.put: %r" % (result, ) except: self._discard(item) raise finally: timeout.cancel()
def put(self, item, block=True, timeout=None): if self.hub is getcurrent(): if self.getters: getter = self.getters.popleft() getter.switch(item) return raise Full if not block: timeout = 0 waiter = Waiter() item = (item, waiter) self.putters.append(item) timeout = Timeout.start_new(timeout, Full) if timeout is not None else None try: if self.getters: self._schedule_unlock() result = waiter.get() if result is not waiter: raise InvalidSwitchError("Invalid switch into Channel.put: %r" % (result, )) except: _safe_remove(self.putters, item) raise finally: if timeout is not None: timeout.cancel()
def kill(self, exception=GreenletExit, block=True, timeout=None): """Raise the ``exception`` in the greenlet. If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires. If block is ``False``, the current greenlet is not unscheduled. The function always returns ``None`` and never raises an error. .. note:: Depending on what this greenlet is executing and the state of the event loop, the exception may or may not be raised immediately when this greenlet resumes execution. It may be raised on a subsequent green call, or, if this greenlet exits before making such a call, it may not be raised at all. As of 1.1, an example where the exception is raised later is if this greenlet had called ``sleep(0)``; an example where the exception is raised immediately is if this greenlet had called ``sleep(0.1)``. See also :func:`gevent.kill`. .. versionchanged:: 0.13.0 *block* is now ``True`` by default. .. versionchanged:: 1.1a2 If this greenlet had never been switched to, killing it will prevent it from ever being switched to. """ self.__cancel_start() if self.dead: self.__handle_death_before_start(exception) else: waiter = Waiter() self.parent.loop.run_callback(_kill, self, exception, waiter) if block: waiter.get() self.join(timeout)
def gethostbyname_ex(self, hostname, family=AF_INET): if PY3: if isinstance(hostname, str): hostname = hostname.encode('idna') elif not isinstance(hostname, (bytes, bytearray)): raise TypeError('Expected es(idna), not %s' % type(hostname).__name__) else: if isinstance(hostname, text_type): hostname = hostname.encode('ascii') elif not isinstance(hostname, str): raise TypeError('Expected string, not %s' % type(hostname).__name__) while True: ares = self.ares try: waiter = Waiter(self.hub) ares.gethostbyname(waiter, hostname, family) result = waiter.get() if not result[-1]: raise gaierror(-5, 'No address associated with hostname') return result except gaierror: if ares is self.ares: raise
def __get_or_peek(self, method, block, timeout): # Internal helper method. The `method` should be either # self._get when called from self.get() or self._peek when # called from self.peek(). Call this after the initial check # to see if there are items in the queue. if self.hub is getcurrent(): # special case to make get_nowait() or peek_nowait() runnable in the mainloop greenlet # there are no items in the queue; try to fix the situation by unlocking putters while self.putters: # Note: get() used popleft(), peek used pop(); popleft # is almost certainly correct. self.putters.popleft().put_and_switch() if self.qsize(): return method() raise Empty() if not block: # We can't block, we're not the hub, and we have nothing # to return. No choice... raise Empty() waiter = Waiter() timeout = Timeout._start_new_or_dummy(timeout, Empty) try: self.getters.append(waiter) if self.putters: self._schedule_unlock() result = waiter.get() if result is not waiter: raise InvalidSwitchError('Invalid switch into Queue.get: %r' % (result, )) return method() finally: timeout.cancel() _safe_remove(self.getters, waiter)
def put(self, item, block=True, timeout=None): if self.hub is getcurrent(): if self.getters: getter = self.getters.popleft() getter.switch(item) return raise Full if not block: timeout = 0 waiter = Waiter() item = (item, waiter) self.putters.append(item) timeout = Timeout._start_new_or_dummy(timeout, Full) try: if self.getters: self._schedule_unlock() result = waiter.get() if result is not waiter: raise InvalidSwitchError("Invalid switch into Channel.put: %r" % (result, )) except: _safe_remove(self.putters, item) raise finally: timeout.cancel()
class Values(object): # helper to collect multiple values; ignore errors unless nothing has succeeded # QQQ could probably be moved somewhere - hub.py? __slots__ = ['count', 'values', 'error', 'waiter', '_synced'] def __init__(self, hub, count): self.count = count self.values = [] self.error = None self.waiter = Waiter(hub) self._synced = False def __call__(self, source): self.count -= 1 if source.exception is None: self.values.append(source.value) else: self.error = source.exception if self.count <= 0: self.waiter.switch() def get(self, throw_on_error=True): if not self._synced: self.waiter.get() self._synced = True if self.values or not throw_on_error: return self.values else: assert error is not None raise self.error # pylint:disable=raising-bad-type
def resolve_reverse_ipv6(packed_ip, flags=0): """Lookup a PTR record for a given IPv6 address. To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``. """ waiter = Waiter() core.dns_resolve_reverse_ipv6(packed_ip, flags, waiter.switch_args) result, _type, ttl, addrs = waiter.get() if result != core.DNS_ERR_NONE: raise DNSError(result) return ttl, addrs
def killall(greenlets, exception=GreenletExit, block=True, polling_period=0.2): """Kill all the greenlets with exception (GreenletExit by default). Wait for them to die if block is true. """ waiter = Waiter() core.active_event(_killall, greenlets, exception, waiter) if block: alive = waiter.wait() if alive: joinall(alive, polling_period=polling_period)
def kill(greenlet, exception=GreenletExit, block=True, polling_period=0.2): """Kill greenlet with exception (GreenletExit by default). Wait for it to die if block is true. """ if not greenlet.dead: waiter = Waiter() core.active_event(_kill, greenlet, exception, waiter) if block: waiter.wait() join(greenlet, polling_period=polling_period)
class GView(AsyncViewBase): def __init__(self, *args, **kwargs): """ Subclass of :class:`~couchbase.async.view.AsyncViewBase` This doesn't expose an API different from the normal synchronous view API. It's just implemented differently """ super(GView, self).__init__(*args, **kwargs) # We use __double_underscore to mangle names. This is because # the views class has quite a bit of data attached to it. self.__waiter = Waiter() self.__iterbufs = deque() self.__done_called = False def raise_include_docs(self): # We allow include_docs in the RowProcessor pass def _callback(self, *args): # Here we need to make sure the callback is invoked # from within the context of the calling greenlet. Since # we're invoked from the hub, we will need to issue more # blocking calls and thus ensure we're not doing the processing # from here. self.__waiter.switch(args) def on_rows(self, rows): self.__iterbufs.appendleft(rows) def on_error(self, ex): raise ex def on_done(self): self.__done_called = True def __wait_rows(self): """ Called when we need more data.. """ args = self.__waiter.get() super(GView, self)._callback(*args) def __iter__(self): if not self._do_iter: raise AlreadyQueriedError.pyexc("Already queried") while self._do_iter and not self.__done_called: self.__wait_rows() while len(self.__iterbufs): ri = self.__iterbufs.pop() for r in ri: yield r self._do_iter = False
def getresponse(self): if self.resp is None: self.conn.make_request(self.req, self.method, self.uri) assert self._waiter is None, self._waiter self._waiter = Waiter() try: self.resp = self._waiter.get() finally: self._waiter = None return self.resp
def resolve_ipv6(name, flags=0): """Lookup an AAAA record for a given *name*. To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``. Returns (ttl, list of packed IPs). """ waiter = Waiter() core.dns_resolve_ipv6(name, flags, waiter.switch_args) result, _type, ttl, addrs = waiter.get() if result != core.DNS_ERR_NONE: raise DNSError(result) return ttl, addrs
def ping(self, value): if self._closed: raise self._failure waiter = Waiter() waiters = self._ping_waiters.get(value) if waiters is not None: waiters.append(waiter) else: self._ping_waiters[value] = [waiter] self._ping_reqs.append(value) self._write_ready.set() return waiter.get()
def __init__(self, *args, **kwargs): """ Subclass of :class:`~couchbase.async.view.AsyncViewBase` This doesn't expose an API different from the normal synchronous view API. It's just implemented differently """ super(GView, self).__init__(*args, **kwargs) # We use __double_underscore to mangle names. This is because # the views class has quite a bit of data attached to it. self.__waiter = Waiter() self.__iterbufs = deque() self.__done_called = False
def gethostbyname_ex(self, hostname, family=AF_INET): while True: ares = self.ares try: waiter = Waiter(self.hub) ares.gethostbyname(waiter, hostname, family) result = waiter.get() if not result[-1]: raise gaierror(-5, 'No address associated with hostname') return result except gaierror: if ares is self.ares: raise
def killall(greenlets, exception=GreenletExit, block=False, timeout=None): if block: waiter = Waiter() core.active_event(_killall3, greenlets, exception, waiter) if block: t = Timeout.start_new(timeout) try: alive = waiter.wait() if alive: joinall(alive, raise_error=False) finally: t.cancel() else: core.active_event(_killall, greenlets, exception)
def resolve_reverse(packed_ip, flags=0): """Lookup a PTR record for a given IP address. To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``. >>> packed_ip = socket.inet_aton('82.94.164.162') >>> resolve_reverse(packed_ip) (10000, 'www.python.org') """ waiter = Waiter() core.dns_resolve_reverse(packed_ip, flags, waiter.switch_args) result, _type, ttl, addr = waiter.get() if result != core.DNS_ERR_NONE: raise DNSError(result) return ttl, addr
def _getnameinfo(self, sockaddr, flags): if not isinstance(flags, int): raise TypeError('an integer is required') if not isinstance(sockaddr, tuple): raise TypeError('getnameinfo() argument 1 must be a tuple') address = sockaddr[0] if not PY3 and isinstance(address, text_type): address = address.encode('ascii') if not isinstance(address, string_types): raise TypeError('sockaddr[0] must be a string, not %s' % type(address).__name__) port = sockaddr[1] if not isinstance(port, int): raise TypeError('port must be an integer, not %s' % type(port)) waiter = Waiter(self.hub) result = self._getaddrinfo(address, str(sockaddr[1]), family=AF_UNSPEC, socktype=SOCK_DGRAM) if not result: reraise(*sys.exc_info()) elif len(result) != 1: raise error('sockaddr resolved to multiple addresses') family, _socktype, _proto, _name, address = result[0] if family == AF_INET: if len(sockaddr) != 2: raise error("IPv4 sockaddr must be 2 tuple") elif family == AF_INET6: address = address[:2] + sockaddr[2:] self.ares.getnameinfo(waiter, address, flags) node, service = waiter.get() if service is None: if PY3: # ares docs: "If the query did not complete # successfully, or one of the values was not # requested, node or service will be NULL ". Python 2 # allows that for the service, but Python 3 raises # an error. This is tested by test_socket in py 3.4 err = gaierror('nodename nor servname provided, or not known') err.errno = 8 raise err service = '0' return node, service
def __init__(self): """ Subclass of :class:`~.AsyncViewBase` This doesn't expose an API different from the normal synchronous view API. It's just implemented differently """ # We use __double_underscore to mangle names. This is because # the views class has quite a bit of data attached to it. self.__waiter = Waiter() self.__raw_rows = [] self.__done_called = False self.start() self.raw.rows_per_call = 100000
def kill(self, exception=GreenletExit, block=False, timeout=None): """Raise the exception in the greenlet. If block is ``False`` (the default), the current greenlet is not unscheduled. If block is ``True``, wait until the greenlet dies or the optional timeout expires. Return ``None``. """ if not self.dead: waiter = Waiter() core.active_event(_kill, self, exception, waiter) if block: waiter.wait() self.join(timeout)
def call_method(self, *args, **kwargs): """Call a method.""" callback = kwargs.get('callback') if callback is not None: super(GEventDBusConnection, self).call_method(*args, **kwargs) return waiter = Waiter() def _gevent_callback(message): waiter.switch(message) kwargs['callback'] = _gevent_callback super(GEventDBusConnection, self).call_method(*args, **kwargs) reply = waiter.get() self._handle_errors(reply) return reply
def kill(self, exception=GreenletExit, block=True, timeout=None): """ Raise the ``exception`` in the greenlet. If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires. If block is ``False``, the current greenlet is not unscheduled. The function always returns ``None`` and never raises an error. .. note:: Depending on what this greenlet is executing and the state of the event loop, the exception may or may not be raised immediately when this greenlet resumes execution. It may be raised on a subsequent green call, or, if this greenlet exits before making such a call, it may not be raised at all. As of 1.1, an example where the exception is raised later is if this greenlet had called :func:`sleep(0) <gevent.sleep>`; an example where the exception is raised immediately is if this greenlet had called :func:`sleep(0.1) <gevent.sleep>`. .. caution:: Use care when killing greenlets. If the code executing is not exception safe (e.g., makes proper use of ``finally``) then an unexpected exception could result in corrupted state. See also :func:`gevent.kill`. :keyword type exception: The type of exception to raise in the greenlet. The default is :class:`GreenletExit`, which indicates a :meth:`successful` completion of the greenlet. .. versionchanged:: 0.13.0 *block* is now ``True`` by default. .. versionchanged:: 1.1a2 If this greenlet had never been switched to, killing it will prevent it from ever being switched to. """ self.__cancel_start() if self.dead: self.__handle_death_before_start(exception) else: waiter = Waiter() if block else None self.parent.loop.run_callback(_kill, self, exception, waiter) if block: waiter.get() self.join(timeout)
def _gethostbyaddr(self, ip_address): waiter = Waiter(self.hub) try: self.ares.gethostbyaddr(waiter, ip_address) return waiter.get() except InvalidIP: result = self._getaddrinfo(ip_address, None, family=AF_UNSPEC, socktype=SOCK_DGRAM) if not result: raise _ip_address = result[0][-1][0] if _ip_address == ip_address: raise waiter.clear() self.ares.gethostbyaddr(waiter, _ip_address) return waiter.get()
def call_method(self, *args, **kwargs): """Call a method.""" callback = kwargs.get('callback') if callback is not None: super(GEventDBusConnection, self).call_method(*args, **kwargs) return waiter = Waiter() def _gevent_callback(message): waiter.switch(message) kwargs['callback'] = _gevent_callback super(GEventDBusConnection, self).call_method(*args, **kwargs) reply = waiter.get() if reply.get_type() == _tdbus.DBUS_MESSAGE_TYPE_ERROR: raise DBusError(reply.get_error_name()) return reply
class TestWaiter(greentest.GenericWaitTestCase): def setUp(self): super(TestWaiter, self).setUp() self.waiter = Waiter() def wait(self, timeout): evt = core.timer(timeout, self.waiter.switch, None) try: return self.waiter.get() finally: evt.cancel() def test(self): waiter = self.waiter self.assertEqual(str(waiter), '<Waiter greenlet=None>') waiter.switch(25) self.assertEqual(str(waiter), '<Waiter greenlet=None value=25>') self.assertEqual(waiter.get(), 25) waiter = Waiter() waiter.throw(ZeroDivisionError) assert re.match( '^<Waiter greenlet=None exc_info=.*ZeroDivisionError.*$', str(waiter)), str(waiter) self.assertRaises(ZeroDivisionError, waiter.get) waiter = Waiter() g = gevent.spawn(waiter.get) gevent.sleep(0) assert str(waiter).startswith('<Waiter greenlet=<Greenlet at '), str( waiter) g.kill()
def killall(greenlets, exception=GreenletExit, block=True, timeout=None): if not greenlets: return loop = greenlets[0].loop if block: waiter = Waiter() loop.run_callback(_killall3, greenlets, exception, waiter) t = Timeout.start_new(timeout) try: alive = waiter.get() if alive: joinall(alive, raise_error=False) finally: t.cancel() else: loop.run_callback(_killall, greenlets, exception)