Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REPL-like printing of final/return value to %%R cell magic #4017

Merged
merged 4 commits into from
Aug 14, 2013
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 34 additions & 10 deletions IPython/extensions/rmagic.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,42 @@ def __init__(self, shell, Rconverter=Rconverter,
self.pyconverter = pyconverter
self.Rconverter = Rconverter

def eval(self, line):
def eval(self, line, line_mode):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's give line_mode a default value so it's clear that it's a boolean.

'''
Parse and evaluate a line with rpy2.
Returns the output to R's stdout() connection
and the value of eval(parse(line)).
Returns the output to R's stdout() connection, and
the value generated by evaluating the code (see below)

In line mode (ie called with %R <stuff>), resulting
values are not printed (explicit calls to the
show/print R functions still result in properly
captured R output).

In cell mode (called with %%R ...), behavior
reproduces the REPL behavior of the R
interpreter (which agrees with how cells of
python code are handled by the notebook).

In cell mode if the last line of code is not
an assignment, wrapped in invisible(), or
a call to a function which returns its value
invisibly, the value will be printed using the
show R function.

Actual evaluation of R code is done via an R
call of the form withVisible({<code>})

'''
old_writeconsole = ri.get_writeconsole()
ri.set_writeconsole(self.write_console)
try:
value = ri.baseenv['eval'](ri.parse(line))
res = ro.r("withVisible({%s})" % line)
value = res[0] #value
except (ri.RRuntimeError, ValueError) as exception:
warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
if not line_mode and ro.conversion.ri2py(res[1])[0]:
ro.r.show(value)
text_output = self.flush()
ri.set_writeconsole(old_writeconsole)
return text_output, value
Expand Down Expand Up @@ -413,13 +436,14 @@ def R(self, line, cell=None, local_ns=None):
In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
Out[9]: array([ 4.25])

As a cell, this will run a block of R code, without bringing anything back by default::
As a cell, this will run a block of R code. By default the resulting value
is printed if it would be when evaluating the same code within an R REPL.
Nothing is returned to python by default.

In [10]: %%R
....: Y = c(2,4,3,9)
....: print(summary(lm(Y~X)))
....:

....: summary(lm(Y~X))

Call:
lm(formula = Y ~ X)

Expand Down Expand Up @@ -580,13 +604,13 @@ def R(self, line, cell=None, local_ns=None):
try:
if line_mode:
for line in code.split(';'):
text_result, result = self.eval(line)
text_result, result = self.eval(line, line_mode)
text_output += text_result
if text_result:
# the last line printed something to the console so we won't return it
return_output = False
else:
text_result, result = self.eval(code)
text_result, result = self.eval(code, line_mode)
text_output += text_result

except RInterpreterError as e:
Expand Down