blocking.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """ Implements a fully blocking kernel client.
  2. Useful for test suites and blocking terminal interfaces.
  3. """
  4. #-----------------------------------------------------------------------------
  5. # Copyright (C) 2012 The IPython Development Team
  6. #
  7. # Distributed under the terms of the BSD License. The full license is in
  8. # the file COPYING.txt, distributed as part of this software.
  9. #-----------------------------------------------------------------------------
  10. try:
  11. from queue import Queue, Empty # Py 3
  12. except ImportError:
  13. from Queue import Queue, Empty # Py 2
  14. # IPython imports
  15. from IPython.utils.io import raw_print
  16. from traitlets import Type
  17. # Local imports
  18. from .channels import (
  19. InProcessChannel,
  20. )
  21. from .client import InProcessKernelClient
  22. class BlockingInProcessChannel(InProcessChannel):
  23. def __init__(self, *args, **kwds):
  24. super(BlockingInProcessChannel, self).__init__(*args, **kwds)
  25. self._in_queue = Queue()
  26. def call_handlers(self, msg):
  27. self._in_queue.put(msg)
  28. def get_msg(self, block=True, timeout=None):
  29. """ Gets a message if there is one that is ready. """
  30. if timeout is None:
  31. # Queue.get(timeout=None) has stupid uninteruptible
  32. # behavior, so wait for a week instead
  33. timeout = 604800
  34. return self._in_queue.get(block, timeout)
  35. def get_msgs(self):
  36. """ Get all messages that are currently ready. """
  37. msgs = []
  38. while True:
  39. try:
  40. msgs.append(self.get_msg(block=False))
  41. except Empty:
  42. break
  43. return msgs
  44. def msg_ready(self):
  45. """ Is there a message that has been received? """
  46. return not self._in_queue.empty()
  47. class BlockingInProcessStdInChannel(BlockingInProcessChannel):
  48. def call_handlers(self, msg):
  49. """ Overridden for the in-process channel.
  50. This methods simply calls raw_input directly.
  51. """
  52. msg_type = msg['header']['msg_type']
  53. if msg_type == 'input_request':
  54. _raw_input = self.client.kernel._sys_raw_input
  55. prompt = msg['content']['prompt']
  56. raw_print(prompt, end='')
  57. self.client.input(_raw_input())
  58. class BlockingInProcessKernelClient(InProcessKernelClient):
  59. # The classes to use for the various channels.
  60. shell_channel_class = Type(BlockingInProcessChannel)
  61. iopub_channel_class = Type(BlockingInProcessChannel)
  62. stdin_channel_class = Type(BlockingInProcessStdInChannel)
  63. def wait_for_ready(self):
  64. # Wait for kernel info reply on shell channel
  65. while True:
  66. msg = self.shell_channel.get_msg(block=True)
  67. if msg['msg_type'] == 'kernel_info_reply':
  68. self._handle_kernel_info_reply(msg)
  69. break
  70. # Flush IOPub channel
  71. while True:
  72. try:
  73. msg = self.iopub_channel.get_msg(block=True, timeout=0.2)
  74. print(msg['msg_type'])
  75. except Empty:
  76. break