Pārlūkot izejas kodu

Pass byte strings straight through LogPrinter

Aanand Prasad 11 gadi atpakaļ
vecāks
revīzija
d0b5bcf26a
3 mainītis faili ar 63 papildinājumiem un 5 dzēšanām
  1. 5 4
      fig/cli/log_printer.py
  2. 1 1
      script/test
  3. 57 0
      tests/unit/log_printer_test.py

+ 5 - 4
fig/cli/log_printer.py

@@ -10,16 +10,17 @@ from .utils import split_buffer
 
 
 class LogPrinter(object):
-    def __init__(self, containers, attach_params=None):
+    def __init__(self, containers, attach_params=None, output=sys.stdout):
         self.containers = containers
         self.attach_params = attach_params or {}
         self.prefix_width = self._calculate_prefix_width(containers)
         self.generators = self._make_log_generators()
+        self.output = output
 
     def run(self):
         mux = Multiplexer(self.generators)
         for line in mux.loop():
-            sys.stdout.write(line.encode(sys.__stdout__.encoding or 'utf-8'))
+            self.output.write(line)
 
     def _calculate_prefix_width(self, containers):
         """
@@ -45,12 +46,12 @@ class LogPrinter(object):
         return generators
 
     def _make_log_generator(self, container, color_fn):
-        prefix = color_fn(self._generate_prefix(container))
+        prefix = color_fn(self._generate_prefix(container)).encode('utf-8')
         # Attach to container before log printer starts running
         line_generator = split_buffer(self._attach(container), '\n')
 
         for line in line_generator:
-            yield prefix + line.decode('utf-8')
+            yield prefix + line
 
         exit_code = container.wait()
         yield color_fn("%s exited with code %s\n" % (container.name, exit_code))

+ 1 - 1
script/test

@@ -1,2 +1,2 @@
 #!/bin/sh
-nosetests $@
+PYTHONIOENCODING=ascii nosetests $@

+ 57 - 0
tests/unit/log_printer_test.py

@@ -0,0 +1,57 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
+import os
+
+from fig.cli.log_printer import LogPrinter
+from .. import unittest
+
+
+class LogPrinterTest(unittest.TestCase):
+    def test_single_container(self):
+        def reader(*args, **kwargs):
+            yield "hello\nworld"
+
+        container = MockContainer(reader)
+        output = run_log_printer([container])
+
+        self.assertIn('hello', output)
+        self.assertIn('world', output)
+
+    def test_unicode(self):
+        glyph = u'\u2022'.encode('utf-8')
+
+        def reader(*args, **kwargs):
+            yield glyph + b'\n'
+
+        container = MockContainer(reader)
+        output = run_log_printer([container])
+
+        self.assertIn(glyph, output)
+
+
+def run_log_printer(containers):
+    r, w = os.pipe()
+    reader, writer = os.fdopen(r, 'r'), os.fdopen(w, 'w')
+    printer = LogPrinter(containers, output=writer)
+    printer.run()
+    writer.close()
+    return reader.read()
+
+
+class MockContainer(object):
+    def __init__(self, reader):
+        self._reader = reader
+
+    @property
+    def name(self):
+        return 'myapp_web_1'
+
+    @property
+    def name_without_project(self):
+        return 'web_1'
+
+    def attach(self, *args, **kwargs):
+        return self._reader()
+
+    def wait(self, *args, **kwargs):
+        return 0