capture.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. # encoding: utf-8
  2. """IO capturing utilities."""
  3. # Copyright (c) IPython Development Team.
  4. # Distributed under the terms of the Modified BSD License.
  5. import sys
  6. from io import StringIO
  7. #-----------------------------------------------------------------------------
  8. # Classes and functions
  9. #-----------------------------------------------------------------------------
  10. class RichOutput(object):
  11. def __init__(self, data=None, metadata=None, transient=None, update=False):
  12. self.data = data or {}
  13. self.metadata = metadata or {}
  14. self.transient = transient or {}
  15. self.update = update
  16. def display(self):
  17. from IPython.display import publish_display_data
  18. publish_display_data(data=self.data, metadata=self.metadata,
  19. transient=self.transient, update=self.update)
  20. def _repr_mime_(self, mime):
  21. if mime not in self.data:
  22. return
  23. data = self.data[mime]
  24. if mime in self.metadata:
  25. return data, self.metadata[mime]
  26. else:
  27. return data
  28. def _repr_mimebundle_(self, include=None, exclude=None):
  29. return self.data, self.metadata
  30. def _repr_html_(self):
  31. return self._repr_mime_("text/html")
  32. def _repr_latex_(self):
  33. return self._repr_mime_("text/latex")
  34. def _repr_json_(self):
  35. return self._repr_mime_("application/json")
  36. def _repr_javascript_(self):
  37. return self._repr_mime_("application/javascript")
  38. def _repr_png_(self):
  39. return self._repr_mime_("image/png")
  40. def _repr_jpeg_(self):
  41. return self._repr_mime_("image/jpeg")
  42. def _repr_svg_(self):
  43. return self._repr_mime_("image/svg+xml")
  44. class CapturedIO(object):
  45. """Simple object for containing captured stdout/err and rich display StringIO objects
  46. Each instance `c` has three attributes:
  47. - ``c.stdout`` : standard output as a string
  48. - ``c.stderr`` : standard error as a string
  49. - ``c.outputs``: a list of rich display outputs
  50. Additionally, there's a ``c.show()`` method which will print all of the
  51. above in the same order, and can be invoked simply via ``c()``.
  52. """
  53. def __init__(self, stdout, stderr, outputs=None):
  54. self._stdout = stdout
  55. self._stderr = stderr
  56. if outputs is None:
  57. outputs = []
  58. self._outputs = outputs
  59. def __str__(self):
  60. return self.stdout
  61. @property
  62. def stdout(self):
  63. "Captured standard output"
  64. if not self._stdout:
  65. return ''
  66. return self._stdout.getvalue()
  67. @property
  68. def stderr(self):
  69. "Captured standard error"
  70. if not self._stderr:
  71. return ''
  72. return self._stderr.getvalue()
  73. @property
  74. def outputs(self):
  75. """A list of the captured rich display outputs, if any.
  76. If you have a CapturedIO object ``c``, these can be displayed in IPython
  77. using::
  78. from IPython.display import display
  79. for o in c.outputs:
  80. display(o)
  81. """
  82. return [ RichOutput(**kargs) for kargs in self._outputs ]
  83. def show(self):
  84. """write my output to sys.stdout/err as appropriate"""
  85. sys.stdout.write(self.stdout)
  86. sys.stderr.write(self.stderr)
  87. sys.stdout.flush()
  88. sys.stderr.flush()
  89. for kargs in self._outputs:
  90. RichOutput(**kargs).display()
  91. __call__ = show
  92. class capture_output(object):
  93. """context manager for capturing stdout/err"""
  94. stdout = True
  95. stderr = True
  96. display = True
  97. def __init__(self, stdout=True, stderr=True, display=True):
  98. self.stdout = stdout
  99. self.stderr = stderr
  100. self.display = display
  101. self.shell = None
  102. def __enter__(self):
  103. from IPython.core.getipython import get_ipython
  104. from IPython.core.displaypub import CapturingDisplayPublisher
  105. from IPython.core.displayhook import CapturingDisplayHook
  106. self.sys_stdout = sys.stdout
  107. self.sys_stderr = sys.stderr
  108. if self.display:
  109. self.shell = get_ipython()
  110. if self.shell is None:
  111. self.save_display_pub = None
  112. self.display = False
  113. stdout = stderr = outputs = None
  114. if self.stdout:
  115. stdout = sys.stdout = StringIO()
  116. if self.stderr:
  117. stderr = sys.stderr = StringIO()
  118. if self.display:
  119. self.save_display_pub = self.shell.display_pub
  120. self.shell.display_pub = CapturingDisplayPublisher()
  121. outputs = self.shell.display_pub.outputs
  122. self.save_display_hook = sys.displayhook
  123. sys.displayhook = CapturingDisplayHook(shell=self.shell,
  124. outputs=outputs)
  125. return CapturedIO(stdout, stderr, outputs)
  126. def __exit__(self, exc_type, exc_value, traceback):
  127. sys.stdout = self.sys_stdout
  128. sys.stderr = self.sys_stderr
  129. if self.display and self.shell:
  130. self.shell.display_pub = self.save_display_pub
  131. sys.displayhook = self.save_display_hook