waiter.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # -*- coding: utf-8 -*-
  2. """
  3. sleekxmpp.xmlstream.handler.waiter
  4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. Part of SleekXMPP: The Sleek XMPP Library
  6. :copyright: (c) 2011 Nathanael C. Fritz
  7. :license: MIT, see LICENSE for more details
  8. """
  9. import logging
  10. from sleekxmpp.util import Queue, QueueEmpty
  11. from sleekxmpp.xmlstream.handler.base import BaseHandler
  12. log = logging.getLogger(__name__)
  13. class Waiter(BaseHandler):
  14. """
  15. The Waiter handler allows an event handler to block until a
  16. particular stanza has been received. The handler will either be
  17. given the matched stanza, or ``False`` if the waiter has timed out.
  18. :param string name: The name of the handler.
  19. :param matcher: A :class:`~sleekxmpp.xmlstream.matcher.base.MatcherBase`
  20. derived object for matching stanza objects.
  21. :param stream: The :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream`
  22. instance this handler should monitor.
  23. """
  24. def __init__(self, name, matcher, stream=None):
  25. BaseHandler.__init__(self, name, matcher, stream=stream)
  26. self._payload = Queue()
  27. def prerun(self, payload):
  28. """Store the matched stanza when received during processing.
  29. :param payload: The matched
  30. :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase` object.
  31. """
  32. self._payload.put(payload)
  33. def run(self, payload):
  34. """Do not process this handler during the main event loop."""
  35. pass
  36. def wait(self, timeout=None):
  37. """Block an event handler while waiting for a stanza to arrive.
  38. Be aware that this will impact performance if called from a
  39. non-threaded event handler.
  40. Will return either the received stanza, or ``False`` if the
  41. waiter timed out.
  42. :param int timeout: The number of seconds to wait for the stanza
  43. to arrive. Defaults to the the stream's
  44. :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream.response_timeout`
  45. value.
  46. """
  47. if timeout is None:
  48. timeout = self.stream().response_timeout
  49. elapsed_time = 0
  50. stanza = False
  51. while elapsed_time < timeout and not self.stream().stop.is_set():
  52. try:
  53. stanza = self._payload.get(True, 1)
  54. break
  55. except QueueEmpty:
  56. elapsed_time += 1
  57. if elapsed_time >= timeout:
  58. log.warning("Timed out waiting for %s", self.name)
  59. self.stream().remove_handler(self.name)
  60. return stanza
  61. def check_delete(self):
  62. """Always remove waiters after use."""
  63. return True