diff --git a/bpython/curtsiesfrontend/repl.py b/bpython/curtsiesfrontend/repl.py index c4614a580..7098dddeb 100644 --- a/bpython/curtsiesfrontend/repl.py +++ b/bpython/curtsiesfrontend/repl.py @@ -229,7 +229,7 @@ def readline(self): value = self.readline_results.pop(0) else: value = 'no saved input available' - self.repl.send_to_stdout(value) + self.repl.send_to_stdouterr(value) return value @@ -333,7 +333,7 @@ def __init__(self, if interp is None: interp = Interp(locals=locals_) - interp.write = self.send_to_stderr + interp.write = self.send_to_stdouterr if banner is None: if config.help_key: banner = (_('Welcome to bpython!') + ' ' + @@ -393,9 +393,9 @@ def __init__(self, # filenos match the backing device for libs that expect it, # but writing to them will do weird things to the display - self.stdout = FakeOutput(self.coderunner, self.send_to_stdout, + self.stdout = FakeOutput(self.coderunner, self.send_to_stdouterr, fileno=sys.__stdout__.fileno()) - self.stderr = FakeOutput(self.coderunner, self.send_to_stderr, + self.stderr = FakeOutput(self.coderunner, self.send_to_stdouterr, fileno=sys.__stderr__.fileno()) self.stdin = FakeStdin(self.coderunner, self, self.edit_keys) @@ -1144,11 +1144,14 @@ def move_current_stdouterr_line_up(self): """Append self.current_stdouterr_line to self.display_lines then clean it.""" self.display_lines.extend(paint.display_linize( - self.current_stdouterr_line, self.width)) + self.current_stdouterr_line, self.width, blank_line=True)) self.current_stdouterr_line = '' - def send_to_stdout(self, output): - """Send unicode string to Repl stdout""" + def send_to_stdouterr(self, output): + """Send unicode strings or FmtStr to Repl stdout or stderr + + Must be able to handle FmtStrs because interpreter pass in + tracebacks already formatted.""" if not output: return lines = output.split('\n') @@ -1163,7 +1166,7 @@ def send_to_stdout(self, output): self.move_current_stdouterr_line_up() if len(lines) > 1: self.display_lines.extend(paint.display_linize( - self.current_stdouterr_line, self.width, blank_line=True)) + self.current_stdouterr_line, self.width)) self.display_lines.extend( sum((paint.display_linize(line, self.width, blank_line=True) @@ -1171,26 +1174,6 @@ def send_to_stdout(self, output): self.current_stdouterr_line = lines[-1] logger.debug('display_lines: %r', self.display_lines) - def send_to_stderr(self, error): - """Send unicode strings or FmtStr to Repl stderr - - Must be able to handle FmtStrs because interpreter pass in - tracebacks already formatted.""" - if not error: - return - lines = error.split('\n') - if all(not line for line in lines): - # If the string consist only of newline characters, - # str.split returns one more empty strings. - lines = lines[:-1] - if lines[-1]: - self.current_stdouterr_line += lines[-1] - else: - self.move_current_stdouterr_line_up() - self.display_lines.extend(sum((paint.display_linize(line, self.width, - blank_line=True) - for line in lines[:-1]), [])) - def send_to_stdin(self, line): if line.endswith('\n'): self.display_lines.extend( @@ -1653,7 +1636,7 @@ def reevaluate(self, insert_into_history=False): if not self.weak_rewind: self.interp = self.interp.__class__() - self.interp.write = self.send_to_stderr + self.interp.write = self.send_to_stdouterr self.coderunner.interp = self.interp self.initialize_interp() diff --git a/bpython/test/test_curtsies_repl.py b/bpython/test/test_curtsies_repl.py index e91fff022..cb28bf84f 100644 --- a/bpython/test/test_curtsies_repl.py +++ b/bpython/test/test_curtsies_repl.py @@ -264,6 +264,38 @@ def test_interactive(self): self.assertEqual(out.getvalue(), '0.5\n0.5\n') +class TestStdOut(TestCase): + def setUp(self): + self.repl = create_repl() + + def test_newline(self): + with captured_output() as (out, err): + self.repl.push('print("\\n")') + self.assertEqual(out.getvalue(), '\n\n') + + def test_leading_newline(self): + with captured_output() as (out, err): + self.repl.push('print("\\nfoo")') + self.assertEqual(out.getvalue(), '\nfoo\n') + + def test_no_trailing_newline(self): + with captured_output() as (out, err): + self.repl.push('print("foo", end="")') + self.assertEqual(out.getvalue(), 'foo') + + def test_print_without_newline_then_print_with_leading_newline(self): + with captured_output() as (out, err): + self.repl.push('print("foo", end="")') + self.repl.push('print("\\nbar")') + self.assertEqual(out.getvalue(), 'foo\nbar\n') + + def test_consecutive_lines(self): + with captured_output() as (out, err): + self.repl.push('for i in range(3):') + self.repl.push(' print("foo")\n') + self.assertEqual(out.getvalue(), 'foo\nfoo\nfoo\n') + + class TestPredictedIndent(TestCase): def setUp(self): self.repl = create_repl()