Robot Framework Integrated Development Environment (RIDE)
outputcapture.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import sys
17 from robotide.lib.robot.utils import StringIO
18 
19 from robotide.lib.robot.output import LOGGER
20 from robotide.lib.robot.utils import console_decode, console_encode, JYTHON
21 
22 
24 
25  def __init__(self, library_import=False):
26  self._library_import_library_import = library_import
27  self._python_out_python_out = PythonCapturer(stdout=True)
28  self._python_err_python_err = PythonCapturer(stdout=False)
29  self._java_out_java_out = JavaCapturer(stdout=True)
30  self._java_err_java_err = JavaCapturer(stdout=False)
31 
32  def __enter__(self):
33  if self._library_import_library_import:
34  LOGGER.enable_library_import_logging()
35  return self
36 
37  def __exit__(self, exc_type, exc_value, exc_trace):
38  self._release_and_log_release_and_log()
39  if self._library_import_library_import:
40  LOGGER.disable_library_import_logging()
41  return False
42 
43  def _release_and_log(self):
44  stdout, stderr = self._release_release()
45  if stdout:
46  LOGGER.log_output(stdout)
47  if stderr:
48  LOGGER.log_output(stderr)
49  sys.__stderr__.write(console_encode(stderr, stream=sys.__stderr__))
50 
51  def _release(self):
52  stdout = self._python_out_python_out.release() + self._java_out_java_out.release()
53  stderr = self._python_err_python_err.release() + self._java_err_java_err.release()
54  return stdout, stderr
55 
56 
58 
59  def __init__(self, stdout=True):
60  if stdout:
61  self._original_original = sys.stdout
62  self._set_stream_set_stream = self._set_stdout_set_stdout
63  else:
64  self._original_original = sys.stderr
65  self._set_stream_set_stream = self._set_stderr_set_stderr
66  self._stream_stream = StringIO()
67  self._set_stream_set_stream(self._stream_stream)
68 
69  def _set_stdout(self, stream):
70  sys.stdout = stream
71 
72  def _set_stderr(self, stream):
73  sys.stderr = stream
74 
75  def release(self):
76  # Original stream must be restored before closing the current
77  self._set_stream_set_stream(self._original_original)
78  try:
79  return self._get_value_get_value(self._stream_stream)
80  finally:
81  self._stream_stream.close()
82  self._avoid_at_exit_errors_avoid_at_exit_errors(self._stream_stream)
83 
84  def _get_value(self, stream):
85  try:
86  return console_decode(stream.getvalue())
87  except UnicodeError:
88  # Error occurs if non-ASCII chars logged both as str and unicode.
89  stream.buf = console_decode(stream.buf)
90  stream.buflist = [console_decode(item) for item in stream.buflist]
91  return stream.getvalue()
92 
93  def _avoid_at_exit_errors(self, stream):
94  # Avoid ValueError at program exit when logging module tries to call
95  # methods of streams it has intercepted that are already closed.
96  # Which methods are called, and does logging silence possible errors,
97  # depends on Python/Jython version. For related discussion see
98  # http://bugs.python.org/issue6333
99  stream.write = lambda s: None
100  stream.flush = lambda: None
101 
102 
103 if not JYTHON:
104 
105  class JavaCapturer():
106 
107  def __init__(self, stdout=True):
108  pass
109 
110  def release(self):
111  return u''
112 
113 else:
114 
115  from java.io import ByteArrayOutputStream, PrintStream
116  from java.lang import System
117 
118  class JavaCapturer():
119 
120  def __init__(self, stdout=True):
121  if stdout:
122  self._original_original = System.out
123  self._set_stream_set_stream = System.setOut
124  else:
125  self._original_original = System.err
126  self._set_stream_set_stream = System.setErr
127  self._bytes_bytes = ByteArrayOutputStream()
128  self._stream_stream = PrintStream(self._bytes_bytes, False, 'UTF-8')
129  self._set_stream_set_stream(self._stream_stream)
130 
131  def release(self):
132  # Original stream must be restored before closing the current
133  self._set_stream_set_stream(self._original_original)
134  self._stream_stream.close()
135  output = self._bytes_bytes.toString('UTF-8')
136  self._bytes_bytes.reset()
137  return output
def __exit__(self, exc_type, exc_value, exc_trace)
def console_decode(string, encoding=CONSOLE_ENCODING, force=False)
Decodes bytes from console encoding to Unicode.
Definition: encoding.py:45
def console_encode(string, errors='replace', stream=sys.__stdout__)
Encodes Unicode to bytes in console or system encoding.
Definition: encoding.py:62