|  | 
| 99 | 99 | - Skipper Seabold, refactoring, cleanups, pure python addition | 
| 100 | 100 | """ | 
| 101 | 101 | from __future__ import print_function | 
|  | 102 | +from __future__ import unicode_literals | 
| 102 | 103 | 
 | 
| 103 | 104 | #----------------------------------------------------------------------------- | 
| 104 | 105 | # Imports | 
| @@ -245,12 +246,35 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout): | 
| 245 | 246 |     return block | 
| 246 | 247 | 
 | 
| 247 | 248 | 
 | 
|  | 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 | + | 
| 248 | 272 | class EmbeddedSphinxShell(object): | 
| 249 | 273 |     """An embedded IPython instance to run inside Sphinx""" | 
| 250 | 274 | 
 | 
| 251 | 275 |     def __init__(self, exec_lines=None,state=None): | 
| 252 | 276 | 
 | 
| 253 |  | -        self.cout = StringIO() | 
|  | 277 | +        self.cout = DecodingStringIO(u'') | 
| 254 | 278 | 
 | 
| 255 | 279 |         if exec_lines is None: | 
| 256 | 280 |             exec_lines = [] | 
| @@ -323,14 +347,6 @@ def process_input_line(self, line, store_history=True): | 
| 323 | 347 |                 self.IP.run_cell(source_raw, store_history=store_history) | 
| 324 | 348 |         finally: | 
| 325 | 349 |             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 | 
| 334 | 350 | 
 | 
| 335 | 351 |     def process_image(self, decorator): | 
| 336 | 352 |         """ | 
| @@ -380,11 +396,12 @@ def process_input(self, data, input_prompt, lineno): | 
| 380 | 396 |         is_savefig = decorator is not None and \ | 
| 381 | 397 |                      decorator.startswith('@savefig') | 
| 382 | 398 | 
 | 
| 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) | 
| 386 | 404 | 
 | 
| 387 |  | -        # input_lines = lmap(_remove_first_space_if_any, input.split('\n')) | 
| 388 | 405 |         input_lines = input.split('\n') | 
| 389 | 406 | 
 | 
| 390 | 407 |         if len(input_lines) > 1: | 
| @@ -716,7 +733,8 @@ class IPythonDirective(Directive): | 
| 716 | 733 |                     'verbatim' : directives.flag, | 
| 717 | 734 |                     'doctest' : directives.flag, | 
| 718 | 735 |                     'okexcept': directives.flag, | 
| 719 |  | -                    'okwarning': directives.flag | 
|  | 736 | +                    'okwarning': directives.flag, | 
|  | 737 | +                    'output_encoding': directives.unchanged_required | 
| 720 | 738 |                   } | 
| 721 | 739 | 
 | 
| 722 | 740 |     shell = None | 
| @@ -817,6 +835,8 @@ def run(self): | 
| 817 | 835 |         self.shell.is_okexcept = 'okexcept' in options | 
| 818 | 836 |         self.shell.is_okwarning = 'okwarning' in options | 
| 819 | 837 | 
 | 
|  | 838 | +        self.shell.output_encoding = [options.get('output_encoding', 'utf8')] | 
|  | 839 | + | 
| 820 | 840 |         # handle pure python code | 
| 821 | 841 |         if 'python' in self.arguments: | 
| 822 | 842 |             content = self.content | 
|  | 
0 commit comments