##// END OF EJS Templates
Handle unicode properly in IPython.zmq.iostream
Thomas Kluyver -
Show More
@@ -1,97 +1,93 b''
1 1 import logging
2 2 import sys
3 3 import time
4 from cStringIO import StringIO
4 from io import StringIO
5 5
6 6 from session import extract_header, Message
7 7
8 8 from IPython.utils import io
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Globals
12 12 #-----------------------------------------------------------------------------
13 13
14 14 # Module-level logger
15 15 logger = logging.getLogger(__name__)
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Stream classes
19 19 #-----------------------------------------------------------------------------
20 20
21 21 class OutStream(object):
22 22 """A file like object that publishes the stream to a 0MQ PUB socket."""
23 23
24 24 # The time interval between automatic flushes, in seconds.
25 25 flush_interval = 0.05
26 26 topic=None
27 27
28 28 def __init__(self, session, pub_socket, name):
29 29 self.session = session
30 30 self.pub_socket = pub_socket
31 31 self.name = name
32 32 self.parent_header = {}
33 33 self._new_buffer()
34 34
35 35 def set_parent(self, parent):
36 36 self.parent_header = extract_header(parent)
37 37
38 38 def close(self):
39 39 self.pub_socket = None
40 40
41 41 def flush(self):
42 42 #io.rprint('>>>flushing output buffer: %s<<<' % self.name) # dbg
43 43 if self.pub_socket is None:
44 44 raise ValueError(u'I/O operation on closed file')
45 45 else:
46 46 data = self._buffer.getvalue()
47 47 if data:
48 # Make sure that we're handling unicode
49 if not isinstance(data, unicode):
50 enc = sys.stdin.encoding or sys.getdefaultencoding()
51 data = data.decode(enc, 'replace')
52 48 content = {u'name':self.name, u'data':data}
53 49 msg = self.session.send(self.pub_socket, u'stream', content=content,
54 50 parent=self.parent_header, ident=self.topic)
55 51 logger.debug(msg)
56 52
57 53 self._buffer.close()
58 54 self._new_buffer()
59 55
60 56 def isatty(self):
61 57 return False
62 58
63 59 def next(self):
64 60 raise IOError('Read not supported on a write only stream.')
65 61
66 62 def read(self, size=-1):
67 63 raise IOError('Read not supported on a write only stream.')
68 64
69 65 def readline(self, size=-1):
70 66 raise IOError('Read not supported on a write only stream.')
71 67
72 68 def write(self, string):
73 69 if self.pub_socket is None:
74 70 raise ValueError('I/O operation on closed file')
75 71 else:
76 # We can only send raw bytes, not unicode objects, so we encode
77 # into utf-8 for all frontends if we get unicode inputs.
78 if type(string) == unicode:
79 string = string.encode('utf-8')
80
72 # Make sure that we're handling unicode
73 if not isinstance(string, unicode):
74 enc = sys.stdin.encoding or sys.getdefaultencoding()
75 string = string.decode(enc, 'replace')
76
81 77 self._buffer.write(string)
82 78 current_time = time.time()
83 79 if self._start <= 0:
84 80 self._start = current_time
85 81 elif current_time - self._start > self.flush_interval:
86 82 self.flush()
87 83
88 84 def writelines(self, sequence):
89 85 if self.pub_socket is None:
90 86 raise ValueError('I/O operation on closed file')
91 87 else:
92 88 for string in sequence:
93 89 self.write(string)
94 90
95 91 def _new_buffer(self):
96 92 self._buffer = StringIO()
97 93 self._start = -1
General Comments 0
You need to be logged in to leave comments. Login now