[tor-commits] [stem/master] Don't use stdout/stderr directly for python output
atagar at torproject.org
atagar at torproject.org
Sun Jul 31 23:04:05 UTC 2016
commit ae48d813dafcae8f46f50d35b758dd5287d178cf
Author: Damian Johnson <atagar at torproject.org>
Date: Sun Jul 31 15:59:47 2016 -0700
Don't use stdout/stderr directly for python output
Python interpreter commands use the builtin InteactiveConsole which interacts
with stdout and stderr directly. This isn't a problem for our tor-prompt since
it writes to stdout anyway, but it breaks nyx.
Nicest option I've found for this is...
https://stackoverflow.com/questions/13250050/redirecting-the-output-of-a-python-function-from-stdout-to-variable-in-python
---
stem/interpreter/commands.py | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/stem/interpreter/commands.py b/stem/interpreter/commands.py
index 82a216d..e348c6e 100644
--- a/stem/interpreter/commands.py
+++ b/stem/interpreter/commands.py
@@ -6,7 +6,9 @@ Handles making requests and formatting the responses.
"""
import code
+import contextlib
import socket
+import sys
import stem
import stem.control
@@ -19,6 +21,11 @@ import stem.util.tor_tools
from stem.interpreter import STANDARD_OUTPUT, BOLD_OUTPUT, ERROR_OUTPUT, uses_settings, msg
from stem.util.term import format
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from io import StringIO
+
def _get_fingerprint(arg, controller):
"""
@@ -84,6 +91,17 @@ def _get_fingerprint(arg, controller):
raise ValueError("'%s' isn't a fingerprint, nickname, or IP address" % arg)
+ at contextlib.contextmanager
+def redirect(stdout, stderr):
+ original = sys.stdout, sys.stderr
+ sys.stdout, sys.stderr = stdout, stderr
+
+ try:
+ yield
+ finally:
+ sys.stdout, sys.stderr = original
+
+
class ControlInterpreter(code.InteractiveConsole):
"""
Handles issuing requests and providing nicely formed responses, with support
@@ -338,8 +356,13 @@ class ControlInterpreter(code.InteractiveConsole):
is_tor_command = cmd in config.get('help.usage', {}) and cmd.lower() != 'events'
if self._run_python_commands and not is_tor_command:
- self.is_multiline_context = code.InteractiveConsole.push(self, command)
- return
+ console_output = StringIO()
+
+ with redirect(console_output, console_output):
+ self.is_multiline_context = code.InteractiveConsole.push(self, command)
+
+ output = console_output.getvalue()
+ return output if output else None
else:
try:
output = format(self._controller.msg(command).raw_content().strip(), *STANDARD_OUTPUT)
More information about the tor-commits
mailing list