##// END OF EJS Templates
Specify unicode type properly in rmagic
Thomas Kluyver -
Show More
@@ -1,693 +1,694 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ======
4 4 Rmagic
5 5 ======
6 6
7 7 Magic command interface for interactive work with R via rpy2
8 8
9 9 .. note::
10 10
11 11 The ``rpy2`` package needs to be installed separately. It
12 12 can be obtained using ``easy_install`` or ``pip``.
13 13
14 14 You will also need a working copy of R.
15 15
16 16 Usage
17 17 =====
18 18
19 19 To enable the magics below, execute ``%load_ext rmagic``.
20 20
21 21 ``%R``
22 22
23 23 {R_DOC}
24 24
25 25 ``%Rpush``
26 26
27 27 {RPUSH_DOC}
28 28
29 29 ``%Rpull``
30 30
31 31 {RPULL_DOC}
32 32
33 33 ``%Rget``
34 34
35 35 {RGET_DOC}
36 36
37 37 """
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Copyright (C) 2012 The IPython Development Team
41 41 #
42 42 # Distributed under the terms of the BSD License. The full license is in
43 43 # the file COPYING, distributed as part of this software.
44 44 #-----------------------------------------------------------------------------
45 45
46 46 import sys
47 47 import tempfile
48 48 from glob import glob
49 49 from shutil import rmtree
50 50
51 51 # numpy and rpy2 imports
52 52
53 53 import numpy as np
54 54
55 55 import rpy2.rinterface as ri
56 56 import rpy2.robjects as ro
57 57 try:
58 58 from rpy2.robjects import pandas2ri
59 59 pandas2ri.activate()
60 60 except ImportError:
61 61 pandas2ri = None
62 62 from rpy2.robjects import numpy2ri
63 63 numpy2ri.activate()
64 64
65 65 # IPython imports
66 66
67 67 from IPython.core.displaypub import publish_display_data
68 68 from IPython.core.magic import (Magics, magics_class, line_magic,
69 69 line_cell_magic, needs_local_scope)
70 70 from IPython.testing.skipdoctest import skip_doctest
71 71 from IPython.core.magic_arguments import (
72 72 argument, magic_arguments, parse_argstring
73 73 )
74 74 from IPython.external.simplegeneric import generic
75 from IPython.utils.py3compat import str_to_unicode, unicode_to_str, PY3
75 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
76 unicode_type)
76 77
77 78 class RInterpreterError(ri.RRuntimeError):
78 79 """An error when running R code in a %%R magic cell."""
79 80 def __init__(self, line, err, stdout):
80 81 self.line = line
81 82 self.err = err.rstrip()
82 83 self.stdout = stdout.rstrip()
83 84
84 85 def __unicode__(self):
85 86 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
86 87 (self.line, self.err)
87 88 if self.stdout and (self.stdout != self.err):
88 89 s += '\nR stdout:\n' + self.stdout
89 90 return s
90 91
91 92 if PY3:
92 93 __str__ = __unicode__
93 94 else:
94 95 def __str__(self):
95 96 return unicode_to_str(unicode(self), 'utf-8')
96 97
97 98 def Rconverter(Robj, dataframe=False):
98 99 """
99 100 Convert an object in R's namespace to one suitable
100 101 for ipython's namespace.
101 102
102 103 For a data.frame, it tries to return a structured array.
103 104 It first checks for colnames, then names.
104 105 If all are NULL, it returns np.asarray(Robj), else
105 106 it tries to construct a recarray
106 107
107 108 Parameters
108 109 ----------
109 110
110 111 Robj: an R object returned from rpy2
111 112 """
112 113 is_data_frame = ro.r('is.data.frame')
113 114 colnames = ro.r('colnames')
114 115 rownames = ro.r('rownames') # with pandas, these could be used for the index
115 116 names = ro.r('names')
116 117
117 118 if dataframe:
118 119 as_data_frame = ro.r('as.data.frame')
119 120 cols = colnames(Robj)
120 121 _names = names(Robj)
121 122 if cols != ri.NULL:
122 123 Robj = as_data_frame(Robj)
123 124 names = tuple(np.array(cols))
124 125 elif _names != ri.NULL:
125 126 names = tuple(np.array(_names))
126 127 else: # failed to find names
127 128 return np.asarray(Robj)
128 129 Robj = np.rec.fromarrays(Robj, names = names)
129 130 return np.asarray(Robj)
130 131
131 132 @generic
132 133 def pyconverter(pyobj):
133 134 """Convert Python objects to R objects. Add types using the decorator:
134 135
135 136 @pyconverter.when_type
136 137 """
137 138 return pyobj
138 139
139 140 # The default conversion for lists seems to make them a nested list. That has
140 141 # some advantages, but is rarely convenient, so for interactive use, we convert
141 142 # lists to a numpy array, which becomes an R vector.
142 143 @pyconverter.when_type(list)
143 144 def pyconverter_list(pyobj):
144 145 return np.asarray(pyobj)
145 146
146 147 if pandas2ri is None:
147 148 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
148 149 # conversion function.
149 150 try:
150 151 from pandas import DataFrame
151 152 from pandas.rpy.common import convert_to_r_dataframe
152 153 @pyconverter.when_type(DataFrame)
153 154 def pyconverter_dataframe(pyobj):
154 155 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
155 156 except ImportError:
156 157 pass
157 158
158 159 @magics_class
159 160 class RMagics(Magics):
160 161 """A set of magics useful for interactive work with R via rpy2.
161 162 """
162 163
163 164 def __init__(self, shell, Rconverter=Rconverter,
164 165 pyconverter=pyconverter,
165 166 cache_display_data=False):
166 167 """
167 168 Parameters
168 169 ----------
169 170
170 171 shell : IPython shell
171 172
172 173 Rconverter : callable
173 174 To be called on values taken from R before putting them in the
174 175 IPython namespace.
175 176
176 177 pyconverter : callable
177 178 To be called on values in ipython namespace before
178 179 assigning to variables in rpy2.
179 180
180 181 cache_display_data : bool
181 182 If True, the published results of the final call to R are
182 183 cached in the variable 'display_cache'.
183 184
184 185 """
185 186 super(RMagics, self).__init__(shell)
186 187 self.cache_display_data = cache_display_data
187 188
188 189 self.r = ro.R()
189 190
190 191 self.Rstdout_cache = []
191 192 self.pyconverter = pyconverter
192 193 self.Rconverter = Rconverter
193 194
194 195 def eval(self, line):
195 196 '''
196 197 Parse and evaluate a line of R code with rpy2.
197 198 Returns the output to R's stdout() connection,
198 199 the value generated by evaluating the code, and a
199 200 boolean indicating whether the return value would be
200 201 visible if the line of code were evaluated in an R REPL.
201 202
202 203 R Code evaluation and visibility determination are
203 204 done via an R call of the form withVisible({<code>})
204 205
205 206 '''
206 207 old_writeconsole = ri.get_writeconsole()
207 208 ri.set_writeconsole(self.write_console)
208 209 try:
209 210 res = ro.r("withVisible({%s})" % line)
210 211 value = res[0] #value (R object)
211 212 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
212 213 except (ri.RRuntimeError, ValueError) as exception:
213 214 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
214 215 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
215 216 text_output = self.flush()
216 217 ri.set_writeconsole(old_writeconsole)
217 218 return text_output, value, visible
218 219
219 220 def write_console(self, output):
220 221 '''
221 222 A hook to capture R's stdout in a cache.
222 223 '''
223 224 self.Rstdout_cache.append(output)
224 225
225 226 def flush(self):
226 227 '''
227 228 Flush R's stdout cache to a string, returning the string.
228 229 '''
229 230 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
230 231 self.Rstdout_cache = []
231 232 return value
232 233
233 234 @skip_doctest
234 235 @needs_local_scope
235 236 @line_magic
236 237 def Rpush(self, line, local_ns=None):
237 238 '''
238 239 A line-level magic for R that pushes
239 240 variables from python to rpy2. The line should be made up
240 241 of whitespace separated variable names in the IPython
241 242 namespace::
242 243
243 244 In [7]: import numpy as np
244 245
245 246 In [8]: X = np.array([4.5,6.3,7.9])
246 247
247 248 In [9]: X.mean()
248 249 Out[9]: 6.2333333333333343
249 250
250 251 In [10]: %Rpush X
251 252
252 253 In [11]: %R mean(X)
253 254 Out[11]: array([ 6.23333333])
254 255
255 256 '''
256 257 if local_ns is None:
257 258 local_ns = {}
258 259
259 260 inputs = line.split(' ')
260 261 for input in inputs:
261 262 try:
262 263 val = local_ns[input]
263 264 except KeyError:
264 265 try:
265 266 val = self.shell.user_ns[input]
266 267 except KeyError:
267 268 # reraise the KeyError as a NameError so that it looks like
268 269 # the standard python behavior when you use an unnamed
269 270 # variable
270 271 raise NameError("name '%s' is not defined" % input)
271 272
272 273 self.r.assign(input, self.pyconverter(val))
273 274
274 275 @skip_doctest
275 276 @magic_arguments()
276 277 @argument(
277 278 '-d', '--as_dataframe', action='store_true',
278 279 default=False,
279 280 help='Convert objects to data.frames before returning to ipython.'
280 281 )
281 282 @argument(
282 283 'outputs',
283 284 nargs='*',
284 285 )
285 286 @line_magic
286 287 def Rpull(self, line):
287 288 '''
288 289 A line-level magic for R that pulls
289 290 variables from python to rpy2::
290 291
291 292 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
292 293
293 294 In [19]: %Rpull x y z
294 295
295 296 In [20]: x
296 297 Out[20]: array([ 3. , 4. , 6.7])
297 298
298 299 In [21]: y
299 300 Out[21]: array([ 4., 6., 7.])
300 301
301 302 In [22]: z
302 303 Out[22]:
303 304 array(['a', '3', '4'],
304 305 dtype='|S1')
305 306
306 307
307 308 If --as_dataframe, then each object is returned as a structured array
308 309 after first passed through "as.data.frame" in R before
309 310 being calling self.Rconverter.
310 311 This is useful when a structured array is desired as output, or
311 312 when the object in R has mixed data types.
312 313 See the %%R docstring for more examples.
313 314
314 315 Notes
315 316 -----
316 317
317 318 Beware that R names can have '.' so this is not fool proof.
318 319 To avoid this, don't name your R objects with '.'s...
319 320
320 321 '''
321 322 args = parse_argstring(self.Rpull, line)
322 323 outputs = args.outputs
323 324 for output in outputs:
324 325 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
325 326
326 327 @skip_doctest
327 328 @magic_arguments()
328 329 @argument(
329 330 '-d', '--as_dataframe', action='store_true',
330 331 default=False,
331 332 help='Convert objects to data.frames before returning to ipython.'
332 333 )
333 334 @argument(
334 335 'output',
335 336 nargs=1,
336 337 type=str,
337 338 )
338 339 @line_magic
339 340 def Rget(self, line):
340 341 '''
341 342 Return an object from rpy2, possibly as a structured array (if possible).
342 343 Similar to Rpull except only one argument is accepted and the value is
343 344 returned rather than pushed to self.shell.user_ns::
344 345
345 346 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
346 347
347 348 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
348 349
349 350 In [5]: %R -i datapy
350 351
351 352 In [6]: %Rget datapy
352 353 Out[6]:
353 354 array([['1', '2', '3', '4'],
354 355 ['2', '3', '2', '5'],
355 356 ['a', 'b', 'c', 'e']],
356 357 dtype='|S1')
357 358
358 359 In [7]: %Rget -d datapy
359 360 Out[7]:
360 361 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
361 362 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
362 363
363 364 '''
364 365 args = parse_argstring(self.Rget, line)
365 366 output = args.output
366 367 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
367 368
368 369
369 370 @skip_doctest
370 371 @magic_arguments()
371 372 @argument(
372 373 '-i', '--input', action='append',
373 374 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
374 375 )
375 376 @argument(
376 377 '-o', '--output', action='append',
377 378 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
378 379 )
379 380 @argument(
380 381 '-w', '--width', type=int,
381 382 help='Width of png plotting device sent as an argument to *png* in R.'
382 383 )
383 384 @argument(
384 385 '-h', '--height', type=int,
385 386 help='Height of png plotting device sent as an argument to *png* in R.'
386 387 )
387 388
388 389 @argument(
389 390 '-d', '--dataframe', action='append',
390 391 help='Convert these objects to data.frames and return as structured arrays.'
391 392 )
392 393 @argument(
393 '-u', '--units', type=unicode, choices=["px", "in", "cm", "mm"],
394 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
394 395 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
395 396 )
396 397 @argument(
397 398 '-r', '--res', type=int,
398 399 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
399 400 )
400 401 @argument(
401 402 '-p', '--pointsize', type=int,
402 403 help='Pointsize of png plotting device sent as an argument to *png* in R.'
403 404 )
404 405 @argument(
405 406 '-b', '--bg',
406 407 help='Background of png plotting device sent as an argument to *png* in R.'
407 408 )
408 409 @argument(
409 410 '-n', '--noreturn',
410 411 help='Force the magic to not return anything.',
411 412 action='store_true',
412 413 default=False
413 414 )
414 415 @argument(
415 416 'code',
416 417 nargs='*',
417 418 )
418 419 @needs_local_scope
419 420 @line_cell_magic
420 421 def R(self, line, cell=None, local_ns=None):
421 422 '''
422 423 Execute code in R, and pull some of the results back into the Python namespace.
423 424
424 425 In line mode, this will evaluate an expression and convert the returned value to a Python object.
425 426 The return value is determined by rpy2's behaviour of returning the result of evaluating the
426 427 final line.
427 428
428 429 Multiple R lines can be executed by joining them with semicolons::
429 430
430 431 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
431 432 Out[9]: array([ 4.25])
432 433
433 434 In cell mode, this will run a block of R code. The resulting value
434 435 is printed if it would printed be when evaluating the same code
435 436 within a standard R REPL.
436 437
437 438 Nothing is returned to python by default in cell mode::
438 439
439 440 In [10]: %%R
440 441 ....: Y = c(2,4,3,9)
441 442 ....: summary(lm(Y~X))
442 443
443 444 Call:
444 445 lm(formula = Y ~ X)
445 446
446 447 Residuals:
447 448 1 2 3 4
448 449 0.88 -0.24 -2.28 1.64
449 450
450 451 Coefficients:
451 452 Estimate Std. Error t value Pr(>|t|)
452 453 (Intercept) 0.0800 2.3000 0.035 0.975
453 454 X 1.0400 0.4822 2.157 0.164
454 455
455 456 Residual standard error: 2.088 on 2 degrees of freedom
456 457 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
457 458 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
458 459
459 460 In the notebook, plots are published as the output of the cell::
460 461
461 462 %R plot(X, Y)
462 463
463 464 will create a scatter plot of X bs Y.
464 465
465 466 If cell is not None and line has some R code, it is prepended to
466 467 the R code in cell.
467 468
468 469 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
469 470
470 471 In [14]: Z = np.array([1,4,5,10])
471 472
472 473 In [15]: %R -i Z mean(Z)
473 474 Out[15]: array([ 5.])
474 475
475 476
476 477 In [16]: %R -o W W=Z*mean(Z)
477 478 Out[16]: array([ 5., 20., 25., 50.])
478 479
479 480 In [17]: W
480 481 Out[17]: array([ 5., 20., 25., 50.])
481 482
482 483 The return value is determined by these rules:
483 484
484 485 * If the cell is not None, the magic returns None.
485 486
486 487 * If the cell evaluates as False, the resulting value is returned
487 488 unless the final line prints something to the console, in
488 489 which case None is returned.
489 490
490 491 * If the final line results in a NULL value when evaluated
491 492 by rpy2, then None is returned.
492 493
493 494 * No attempt is made to convert the final value to a structured array.
494 495 Use the --dataframe flag or %Rget to push / return a structured array.
495 496
496 497 * If the -n flag is present, there is no return value.
497 498
498 499 * A trailing ';' will also result in no return value as the last
499 500 value in the line is an empty string.
500 501
501 502 The --dataframe argument will attempt to return structured arrays.
502 503 This is useful for dataframes with
503 504 mixed data types. Note also that for a data.frame,
504 505 if it is returned as an ndarray, it is transposed::
505 506
506 507 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
507 508
508 509 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
509 510
510 511 In [20]: %%R -o datar
511 512 datar = datapy
512 513 ....:
513 514
514 515 In [21]: datar
515 516 Out[21]:
516 517 array([['1', '2', '3', '4'],
517 518 ['2', '3', '2', '5'],
518 519 ['a', 'b', 'c', 'e']],
519 520 dtype='|S1')
520 521
521 522 In [22]: %%R -d datar
522 523 datar = datapy
523 524 ....:
524 525
525 526 In [23]: datar
526 527 Out[23]:
527 528 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
528 529 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
529 530
530 531 The --dataframe argument first tries colnames, then names.
531 532 If both are NULL, it returns an ndarray (i.e. unstructured)::
532 533
533 534 In [1]: %R mydata=c(4,6,8.3); NULL
534 535
535 536 In [2]: %R -d mydata
536 537
537 538 In [3]: mydata
538 539 Out[3]: array([ 4. , 6. , 8.3])
539 540
540 541 In [4]: %R names(mydata) = c('a','b','c'); NULL
541 542
542 543 In [5]: %R -d mydata
543 544
544 545 In [6]: mydata
545 546 Out[6]:
546 547 array((4.0, 6.0, 8.3),
547 548 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
548 549
549 550 In [7]: %R -o mydata
550 551
551 552 In [8]: mydata
552 553 Out[8]: array([ 4. , 6. , 8.3])
553 554
554 555 '''
555 556
556 557 args = parse_argstring(self.R, line)
557 558
558 559 # arguments 'code' in line are prepended to
559 560 # the cell lines
560 561
561 562 if cell is None:
562 563 code = ''
563 564 return_output = True
564 565 line_mode = True
565 566 else:
566 567 code = cell
567 568 return_output = False
568 569 line_mode = False
569 570
570 571 code = ' '.join(args.code) + code
571 572
572 573 # if there is no local namespace then default to an empty dict
573 574 if local_ns is None:
574 575 local_ns = {}
575 576
576 577 if args.input:
577 578 for input in ','.join(args.input).split(','):
578 579 try:
579 580 val = local_ns[input]
580 581 except KeyError:
581 582 try:
582 583 val = self.shell.user_ns[input]
583 584 except KeyError:
584 585 raise NameError("name '%s' is not defined" % input)
585 586 self.r.assign(input, self.pyconverter(val))
586 587
587 588 if getattr(args, 'units') is not None:
588 589 if args.units != "px" and getattr(args, 'res') is None:
589 590 args.res = 72
590 591 args.units = '"%s"' % args.units
591 592
592 593 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
593 594 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
594 595 # execute the R code in a temporary directory
595 596
596 597 tmpd = tempfile.mkdtemp()
597 598 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
598 599
599 600 text_output = ''
600 601 try:
601 602 if line_mode:
602 603 for line in code.split(';'):
603 604 text_result, result, visible = self.eval(line)
604 605 text_output += text_result
605 606 if text_result:
606 607 # the last line printed something to the console so we won't return it
607 608 return_output = False
608 609 else:
609 610 text_result, result, visible = self.eval(code)
610 611 text_output += text_result
611 612 if visible:
612 613 old_writeconsole = ri.get_writeconsole()
613 614 ri.set_writeconsole(self.write_console)
614 615 ro.r.show(result)
615 616 text_output += self.flush()
616 617 ri.set_writeconsole(old_writeconsole)
617 618
618 619 except RInterpreterError as e:
619 620 print(e.stdout)
620 621 if not e.stdout.endswith(e.err):
621 622 print(e.err)
622 623 rmtree(tmpd)
623 624 return
624 625
625 626 self.r('dev.off()')
626 627
627 628 # read out all the saved .png files
628 629
629 630 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
630 631
631 632 # now publish the images
632 633 # mimicking IPython/zmq/pylab/backend_inline.py
633 634 fmt = 'png'
634 635 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
635 636 mime = mimetypes[fmt]
636 637
637 638 # publish the printed R objects, if any
638 639
639 640 display_data = []
640 641 if text_output:
641 642 display_data.append(('RMagic.R', {'text/plain':text_output}))
642 643
643 644 # flush text streams before sending figures, helps a little with output
644 645 for image in images:
645 646 # synchronization in the console (though it's a bandaid, not a real sln)
646 647 sys.stdout.flush(); sys.stderr.flush()
647 648 display_data.append(('RMagic.R', {mime: image}))
648 649
649 650 # kill the temporary directory
650 651 rmtree(tmpd)
651 652
652 653 # try to turn every output into a numpy array
653 654 # this means that output are assumed to be castable
654 655 # as numpy arrays
655 656
656 657 if args.output:
657 658 for output in ','.join(args.output).split(','):
658 659 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
659 660
660 661 if args.dataframe:
661 662 for output in ','.join(args.dataframe).split(','):
662 663 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
663 664
664 665 for tag, disp_d in display_data:
665 666 publish_display_data(tag, disp_d)
666 667
667 668 # this will keep a reference to the display_data
668 669 # which might be useful to other objects who happen to use
669 670 # this method
670 671
671 672 if self.cache_display_data:
672 673 self.display_cache = display_data
673 674
674 675 # if in line mode and return_output, return the result as an ndarray
675 676 if return_output and not args.noreturn:
676 677 if result != ri.NULL:
677 678 return self.Rconverter(result, dataframe=False)
678 679
679 680 __doc__ = __doc__.format(
680 681 R_DOC = ' '*8 + RMagics.R.__doc__,
681 682 RPUSH_DOC = ' '*8 + RMagics.Rpush.__doc__,
682 683 RPULL_DOC = ' '*8 + RMagics.Rpull.__doc__,
683 684 RGET_DOC = ' '*8 + RMagics.Rget.__doc__
684 685 )
685 686
686 687
687 688 def load_ipython_extension(ip):
688 689 """Load the extension in IPython."""
689 690 ip.register_magics(RMagics)
690 691 # Initialising rpy2 interferes with readline. Since, at this point, we've
691 692 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
692 693 if ip.has_readline:
693 694 ip.readline.set_completer_delims(ip.readline_delims)
@@ -1,204 +1,206 b''
1 1 # coding: utf-8
2 2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 3 import __builtin__
4 4 import functools
5 5 import sys
6 6 import re
7 7 import types
8 8
9 9 from .encoding import DEFAULT_ENCODING
10 10
11 11 orig_open = open
12 12
13 13 def no_code(x, encoding=None):
14 14 return x
15 15
16 16 def decode(s, encoding=None):
17 17 encoding = encoding or DEFAULT_ENCODING
18 18 return s.decode(encoding, "replace")
19 19
20 20 def encode(u, encoding=None):
21 21 encoding = encoding or DEFAULT_ENCODING
22 22 return u.encode(encoding, "replace")
23 23
24 24
25 25 def cast_unicode(s, encoding=None):
26 26 if isinstance(s, bytes):
27 27 return decode(s, encoding)
28 28 return s
29 29
30 30 def cast_bytes(s, encoding=None):
31 31 if not isinstance(s, bytes):
32 32 return encode(s, encoding)
33 33 return s
34 34
35 35 def _modify_str_or_docstring(str_change_func):
36 36 @functools.wraps(str_change_func)
37 37 def wrapper(func_or_str):
38 38 if isinstance(func_or_str, basestring):
39 39 func = None
40 40 doc = func_or_str
41 41 else:
42 42 func = func_or_str
43 43 doc = func.__doc__
44 44
45 45 doc = str_change_func(doc)
46 46
47 47 if func:
48 48 func.__doc__ = doc
49 49 return func
50 50 return doc
51 51 return wrapper
52 52
53 53 def safe_unicode(e):
54 54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
55 55 safe to call unicode() on.
56 56 """
57 57 try:
58 58 return unicode(e)
59 59 except UnicodeError:
60 60 pass
61 61
62 62 try:
63 63 return str_to_unicode(str(e))
64 64 except UnicodeError:
65 65 pass
66 66
67 67 try:
68 68 return str_to_unicode(repr(e))
69 69 except UnicodeError:
70 70 pass
71 71
72 72 return u'Unrecoverably corrupt evalue'
73 73
74 74 if sys.version_info[0] >= 3:
75 75 PY3 = True
76 76
77 77 input = input
78 78 builtin_mod_name = "builtins"
79 79
80 80 str_to_unicode = no_code
81 81 unicode_to_str = no_code
82 82 str_to_bytes = encode
83 83 bytes_to_str = decode
84 84 cast_bytes_py2 = no_code
85 85
86 86 string_types = (str,)
87 unicode_type = str
87 88
88 89 def isidentifier(s, dotted=False):
89 90 if dotted:
90 91 return all(isidentifier(a) for a in s.split("."))
91 92 return s.isidentifier()
92 93
93 94 open = orig_open
94 95
95 96 MethodType = types.MethodType
96 97
97 98 def execfile(fname, glob, loc=None):
98 99 loc = loc if (loc is not None) else glob
99 100 with open(fname, 'rb') as f:
100 101 exec compile(f.read(), fname, 'exec') in glob, loc
101 102
102 103 # Refactor print statements in doctests.
103 104 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
104 105 def _print_statement_sub(match):
105 106 expr = match.groups('expr')
106 107 return "print(%s)" % expr
107 108
108 109 @_modify_str_or_docstring
109 110 def doctest_refactor_print(doc):
110 111 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
111 112 unfortunately doesn't pick up on our doctests.
112 113
113 114 Can accept a string or a function, so it can be used as a decorator."""
114 115 return _print_statement_re.sub(_print_statement_sub, doc)
115 116
116 117 # Abstract u'abc' syntax:
117 118 @_modify_str_or_docstring
118 119 def u_format(s):
119 120 """"{u}'abc'" --> "'abc'" (Python 3)
120 121
121 122 Accepts a string or a function, so it can be used as a decorator."""
122 123 return s.format(u='')
123 124
124 125 else:
125 126 PY3 = False
126 127
127 128 input = raw_input
128 129 builtin_mod_name = "__builtin__"
129 130
130 131 str_to_unicode = decode
131 132 unicode_to_str = encode
132 133 str_to_bytes = no_code
133 134 bytes_to_str = no_code
134 135 cast_bytes_py2 = cast_bytes
135 136
136 137 string_types = (str, unicode)
138 unicode_type = unicode
137 139
138 140 import re
139 141 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
140 142 def isidentifier(s, dotted=False):
141 143 if dotted:
142 144 return all(isidentifier(a) for a in s.split("."))
143 145 return bool(_name_re.match(s))
144 146
145 147 class open(object):
146 148 """Wrapper providing key part of Python 3 open() interface."""
147 149 def __init__(self, fname, mode="r", encoding="utf-8"):
148 150 self.f = orig_open(fname, mode)
149 151 self.enc = encoding
150 152
151 153 def write(self, s):
152 154 return self.f.write(s.encode(self.enc))
153 155
154 156 def read(self, size=-1):
155 157 return self.f.read(size).decode(self.enc)
156 158
157 159 def close(self):
158 160 return self.f.close()
159 161
160 162 def __enter__(self):
161 163 return self
162 164
163 165 def __exit__(self, etype, value, traceback):
164 166 self.f.close()
165 167
166 168 def MethodType(func, instance):
167 169 return types.MethodType(func, instance, type(instance))
168 170
169 171 # don't override system execfile on 2.x:
170 172 execfile = execfile
171 173
172 174 def doctest_refactor_print(func_or_str):
173 175 return func_or_str
174 176
175 177
176 178 # Abstract u'abc' syntax:
177 179 @_modify_str_or_docstring
178 180 def u_format(s):
179 181 """"{u}'abc'" --> "u'abc'" (Python 2)
180 182
181 183 Accepts a string or a function, so it can be used as a decorator."""
182 184 return s.format(u='u')
183 185
184 186 if sys.platform == 'win32':
185 187 def execfile(fname, glob=None, loc=None):
186 188 loc = loc if (loc is not None) else glob
187 189 # The rstrip() is necessary b/c trailing whitespace in files will
188 190 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
189 191 # but we still support 2.6). See issue 1027.
190 192 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
191 193 # compile converts unicode filename to str assuming
192 194 # ascii. Let's do the conversion before calling compile
193 195 if isinstance(fname, unicode):
194 196 filename = unicode_to_str(fname)
195 197 else:
196 198 filename = fname
197 199 exec compile(scripttext, filename, 'exec') in glob, loc
198 200 else:
199 201 def execfile(fname, *where):
200 202 if isinstance(fname, unicode):
201 203 filename = fname.encode(sys.getfilesystemencoding())
202 204 else:
203 205 filename = fname
204 206 __builtin__.execfile(filename, *where)
General Comments 0
You need to be logged in to leave comments. Login now