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