Skip to content

Commit b484a9f

Browse files
author
y-p
committed
Merge pull request #6185 from y-p/PR_ip_d_unicode
BLD: ipython_directive, handle non-ascii execution results
2 parents 1775ba1 + 7393a61 commit b484a9f

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

doc/source/conf.py

+10
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,16 @@
285285
'wiki': ('https://github.com/pydata/pandas/wiki/%s',
286286
'wiki ')}
287287

288+
ipython_exec_lines = [
289+
'import numpy as np',
290+
'import pandas as pd',
291+
# This ensures correct rendering on system with console encoding != utf8
292+
# (windows). It forces pandas to encode it's output reprs using utf8
293+
# whereever the docs are built. The docs' target is the browser, not
294+
# the console, so this is fine.
295+
'pd.options.display.encoding="utf8"'
296+
]
297+
288298
# remove the docstring of the flags attribute (inherited from numpy ndarray)
289299
# because these give doc build errors (see GH issue 5331)
290300
def remove_flags_docstring(app, what, name, obj, options, lines):

doc/sphinxext/ipython_directive.py

+34-14
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
- Skipper Seabold, refactoring, cleanups, pure python addition
100100
"""
101101
from __future__ import print_function
102+
from __future__ import unicode_literals
102103

103104
#-----------------------------------------------------------------------------
104105
# Imports
@@ -245,12 +246,35 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout):
245246
return block
246247

247248

249+
class DecodingStringIO(StringIO, object):
250+
def __init__(self,buf='',encodings=('utf8',), *args, **kwds):
251+
super(DecodingStringIO, self).__init__(buf, *args, **kwds)
252+
self.set_encodings(encodings)
253+
254+
def set_encodings(self, encodings):
255+
self.encodings = encodings
256+
257+
def write(self,data):
258+
#py 3 compat here
259+
if isinstance(data,unicode):
260+
return super(DecodingStringIO, self).write(data)
261+
else:
262+
for enc in self.encodings:
263+
try:
264+
data = data.decode(enc)
265+
return super(DecodingStringIO, self).write(data)
266+
except :
267+
pass
268+
# default to brute utf8 if no encoding succeded
269+
return super(DecodingStringIO, self).write(data.decode('utf8', 'replace'))
270+
271+
248272
class EmbeddedSphinxShell(object):
249273
"""An embedded IPython instance to run inside Sphinx"""
250274

251275
def __init__(self, exec_lines=None,state=None):
252276

253-
self.cout = StringIO()
277+
self.cout = DecodingStringIO(u'')
254278

255279
if exec_lines is None:
256280
exec_lines = []
@@ -323,14 +347,6 @@ def process_input_line(self, line, store_history=True):
323347
self.IP.run_cell(source_raw, store_history=store_history)
324348
finally:
325349
sys.stdout = stdout
326-
buflist = self.cout.buflist
327-
for i in range(len(buflist)):
328-
try:
329-
# print(buflist[i])
330-
if not isinstance(buflist[i], unicode):
331-
buflist[i] = buflist[i].decode('utf8','replace')
332-
except:
333-
pass
334350

335351
def process_image(self, decorator):
336352
"""
@@ -380,11 +396,12 @@ def process_input(self, data, input_prompt, lineno):
380396
is_savefig = decorator is not None and \
381397
decorator.startswith('@savefig')
382398

383-
# #>>> required for cython magic to work
384-
# def _remove_first_space_if_any(line):
385-
# return line[1:] if line.startswith(' ') else line
399+
# set the encodings to be used by DecodingStringIO
400+
# to convert the execution output into unicode if
401+
# needed. this attrib is set by IpythonDirective.run()
402+
# based on the specified block options, defaulting to ['ut
403+
self.cout.set_encodings(self.output_encoding)
386404

387-
# input_lines = lmap(_remove_first_space_if_any, input.split('\n'))
388405
input_lines = input.split('\n')
389406

390407
if len(input_lines) > 1:
@@ -716,7 +733,8 @@ class IPythonDirective(Directive):
716733
'verbatim' : directives.flag,
717734
'doctest' : directives.flag,
718735
'okexcept': directives.flag,
719-
'okwarning': directives.flag
736+
'okwarning': directives.flag,
737+
'output_encoding': directives.unchanged_required
720738
}
721739

722740
shell = None
@@ -817,6 +835,8 @@ def run(self):
817835
self.shell.is_okexcept = 'okexcept' in options
818836
self.shell.is_okwarning = 'okwarning' in options
819837

838+
self.shell.output_encoding = [options.get('output_encoding', 'utf8')]
839+
820840
# handle pure python code
821841
if 'python' in self.arguments:
822842
content = self.content

0 commit comments

Comments
 (0)