def setUp(self): self.console = rinterface.get_writeconsole_regular() def noconsole(x): pass rinterface.set_writeconsole_regular(noconsole)
def eval(self, code): """ Parse and evaluate a line of R code with rpy2. Returns the output to R's stdout() connection, the value generated by evaluating the code, and a boolean indicating whether the return value would be visible if the line of code were evaluated in an R REPL. R Code evaluation and visibility determination are done via an R call of the form withVisible(code_string), and this entire expression needs to be evaluated in R (we can't use rpy2 function proxies here, as withVisible is a LISPy R function). """ old_writeconsole_regular = ri.get_writeconsole_regular() ri.set_writeconsole_regular(self.write_console_regular) try: # Need the newline in case the last line in code is a comment value, visible = ro.r("withVisible({%s\n})" % code) except (ri.RRuntimeError, ValueError) as exception: warning_or_other_msg = self.flush( ) # otherwise next return seems to have copy of error raise RInterpreterError(code, str(exception), warning_or_other_msg) text_output = self.flush() ri.set_writeconsole_regular(old_writeconsole_regular) return text_output, value, visible[0]
def eval(self, code): ''' Parse and evaluate a line of R code with rpy2. Returns the output to R's stdout() connection, the value generated by evaluating the code, and a boolean indicating whether the return value would be visible if the line of code were evaluated in an R REPL. R Code evaluation and visibility determination are done via an R call of the form withVisible(code_string), and this entire expression needs to be evaluated in R (we can't use rpy2 function proxies here, as withVisible is a LISPy R function). ''' old_writeconsole_regular = ri.get_writeconsole_regular() ri.set_writeconsole_regular(self.write_console_regular) try: # Need the newline in case the last line in code is a comment value, visible = ro.r("withVisible({%s\n})" % code) except (ri.RRuntimeError, ValueError) as exception: warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error raise RInterpreterError(code, str_to_unicode(str(exception)), warning_or_other_msg) text_output = self.flush() ri.set_writeconsole_regular(old_writeconsole_regular) return text_output, value, visible[0]
def testSetWriteConsoleRegular(self): buf = [] def f(x): buf.append(x) rinterface.set_writeconsole_regular(f) self.assertEqual(rinterface.get_writeconsole_regular(), f) code = rinterface.SexpVector(["3", ], rinterface.STRSXP) rinterface.baseenv["print"](code) self.assertEqual('[1] "3"\n', str.join('', buf))
def testSetWriteConsoleRegular(self): buf = [] def f(x): buf.append(x) rinterface.set_writeconsole_regular(f) self.assertEqual(rinterface.get_writeconsole_regular(), f) code = rinterface.SexpVector([ "3", ], rinterface.STRSXP) rinterface.baseenv["print"](code) self.assertEqual('[1] "3"\n', str.join('', buf))
def R(self, line, cell=None, local_ns=None): """ Execute code in R, optionally returning results to the Python runtime. In line mode, this will evaluate an expression and convert the returned value to a Python object. The return value is determined by rpy2's behaviour of returning the result of evaluating the final expression. Multiple R expressions can be executed by joining them with semicolons:: In [9]: %R X=c(1,4,5,7); sd(X); mean(X) Out[9]: array([ 4.25]) In cell mode, this will run a block of R code. The resulting value is printed if it would be printed when evaluating the same code within a standard R REPL. Nothing is returned to python by default in cell mode:: In [10]: %%R ....: Y = c(2,4,3,9) ....: summary(lm(Y~X)) Call: lm(formula = Y ~ X) Residuals: 1 2 3 4 0.88 -0.24 -2.28 1.64 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 0.0800 2.3000 0.035 0.975 X 1.0400 0.4822 2.157 0.164 Residual standard error: 2.088 on 2 degrees of freedom Multiple R-squared: 0.6993,Adjusted R-squared: 0.549 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638 In the notebook, plots are published as the output of the cell:: %R plot(X, Y) will create a scatter plot of X bs Y. If cell is not None and line has some R code, it is prepended to the R code in cell. Objects can be passed back and forth between rpy2 and python via the -i -o flags in line:: In [14]: Z = np.array([1,4,5,10]) In [15]: %R -i Z mean(Z) Out[15]: array([ 5.]) In [16]: %R -o W W=Z*mean(Z) Out[16]: array([ 5., 20., 25., 50.]) In [17]: W Out[17]: array([ 5., 20., 25., 50.]) The return value is determined by these rules: * If the cell is not None (i.e., has contents), the magic returns None. * If the final line results in a NULL value when evaluated by rpy2, then None is returned. * No attempt is made to convert the final value to a structured array. Use %Rget to push a structured array. * If the -n flag is present, there is no return value. * A trailing ';' will also result in no return value as the last value in the line is an empty string. """ args = parse_argstring(self.R, line) # arguments 'code' in line are prepended to # the cell lines if cell is None: code = '' return_output = True line_mode = True else: code = cell return_output = False line_mode = False code = ' '.join(args.code) + code # if there is no local namespace then default to an empty dict if local_ns is None: local_ns = {} if args.converter is None: converter = self.converter else: try: converter = local_ns[args.converter] except KeyError: try: converter = self.shell.user_ns[args.converter] except KeyError: raise NameError("name '%s' is not defined" % args.converter) if not isinstance(converter, Converter): raise ValueError( "'%s' must be a %s object (but it is a %s)." % (args.converter, Converter, type(localconverter))) if args.input: for input in ','.join(args.input).split(','): try: val = local_ns[input] except KeyError: try: val = self.shell.user_ns[input] except KeyError: raise NameError("name '%s' is not defined" % input) with localconverter(converter) as cv: ro.r.assign(input, val) tmpd = self.setup_graphics(args) text_output = '' try: if line_mode: for line in code.split(';'): text_result, result, visible = self.eval(line) 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, visible = self.eval(code) text_output += text_result if visible: old_writeconsole_regular = ri.get_writeconsole_regular() ri.set_writeconsole_regular(self.write_console_regular) ro.r.show(result) text_output += self.flush() ri.set_writeconsole_regular(old_writeconsole_regular) except RInterpreterError as e: # TODO: Maybe we should make this red or something? print(e.stdout) if not e.stdout.endswith(e.err): print(e.err) if tmpd: rmtree(tmpd) return finally: if self.device in ['png', 'svg']: ro.r('dev.off()') if text_output: # display_data.append(('RMagic.R', {'text/plain':text_output})) publish_display_data(data={'text/plain': text_output}, source='RMagic.R') # publish the R images if self.device in ['png', 'svg']: display_data, md = self.publish_graphics(tmpd, args.isolate_svgs) for tag, disp_d in display_data: publish_display_data(data=disp_d, source=tag, metadata=md) # kill the temporary directory - currently created only for "svg" # and "png" (else it's None) rmtree(tmpd) if args.output: with localconverter(converter) as cv: for output in ','.join(args.output).split(','): output_ipy = ro.globalenv.get(output) self.shell.push({output: output_ipy}) # this will keep a reference to the display_data # which might be useful to other objects who happen to use # this method if self.cache_display_data: self.display_cache = display_data # We're in line mode and return_output is still True, # so return the converted result if return_output and not args.noreturn: if result is not ri.NULL: with localconverter(converter) as cv: res = cv.ri2py(result) return res
def R(self, line, cell=None, local_ns=None): ''' Execute code in R, optionally returning results to the Python runtime. In line mode, this will evaluate an expression and convert the returned value to a Python object. The return value is determined by rpy2's behaviour of returning the result of evaluating the final expression. Multiple R expressions can be executed by joining them with semicolons:: In [9]: %R X=c(1,4,5,7); sd(X); mean(X) Out[9]: array([ 4.25]) In cell mode, this will run a block of R code. The resulting value is printed if it would be printed when evaluating the same code within a standard R REPL. Nothing is returned to python by default in cell mode:: In [10]: %%R ....: Y = c(2,4,3,9) ....: summary(lm(Y~X)) Call: lm(formula = Y ~ X) Residuals: 1 2 3 4 0.88 -0.24 -2.28 1.64 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 0.0800 2.3000 0.035 0.975 X 1.0400 0.4822 2.157 0.164 Residual standard error: 2.088 on 2 degrees of freedom Multiple R-squared: 0.6993,Adjusted R-squared: 0.549 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638 In the notebook, plots are published as the output of the cell:: %R plot(X, Y) will create a scatter plot of X bs Y. If cell is not None and line has some R code, it is prepended to the R code in cell. Objects can be passed back and forth between rpy2 and python via the -i -o flags in line:: In [14]: Z = np.array([1,4,5,10]) In [15]: %R -i Z mean(Z) Out[15]: array([ 5.]) In [16]: %R -o W W=Z*mean(Z) Out[16]: array([ 5., 20., 25., 50.]) In [17]: W Out[17]: array([ 5., 20., 25., 50.]) The return value is determined by these rules: * If the cell is not None (i.e., has contents), the magic returns None. * If the final line results in a NULL value when evaluated by rpy2, then None is returned. * No attempt is made to convert the final value to a structured array. Use %Rget to push a structured array. * If the -n flag is present, there is no return value. * A trailing ';' will also result in no return value as the last value in the line is an empty string. ''' args = parse_argstring(self.R, line) # arguments 'code' in line are prepended to # the cell lines if cell is None: code = '' return_output = True line_mode = True else: code = cell return_output = False line_mode = False code = ' '.join(args.code) + code # if there is no local namespace then default to an empty dict if local_ns is None: local_ns = {} if args.converter is None: pass else: try: localconverter = local_ns[args.converter] except KeyError: try: localconverter = self.shell.user_ns[args.converter] except KeyError: raise NameError("name '%s' is not defined" % args.converter) if not isinstance(localconverter, Converter): raise ValueError("'%s' must be a Converter object.") if args.input: for input in ','.join(args.input).split(','): try: val = local_ns[input] except KeyError: try: val = self.shell.user_ns[input] except KeyError: raise NameError("name '%s' is not defined" % input) if args.converter is None: ro.r.assign(input, self.pyconverter(val)) else: ro.r.assign(input, localconverter.py2ri(val)) tmpd = self.setup_graphics(args) text_output = '' try: if line_mode: for line in code.split(';'): text_result, result, visible = self.eval(line) 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, visible = self.eval(code) text_output += text_result if visible: old_writeconsole_regular = ri.get_writeconsole_regular() ri.set_writeconsole_regular(self.write_console_regular) ro.r.show(result) text_output += self.flush() ri.set_writeconsole_regular(old_writeconsole_regular) except RInterpreterError as e: # XXX - Maybe we should make this red or something? print(e.stdout) if not e.stdout.endswith(e.err): print(e.err) if tmpd: rmtree(tmpd) return finally: if self.device in ['png', 'svg']: ro.r('dev.off()') if text_output: # display_data.append(('RMagic.R', {'text/plain':text_output})) publish_display_data(data={'text/plain':text_output}, source='RMagic.R') # publish the R images if self.device in ['png', 'svg']: display_data, md = self.publish_graphics(tmpd, args.isolate_svgs) for tag, disp_d in display_data: publish_display_data(data=disp_d, source=tag, metadata=md) # kill the temporary directory - currently created only for "svg" # and "png" (else it's None) rmtree(tmpd) if args.output: for output in ','.join(args.output).split(','): if args.converter is None: output_ipy = converter.ri2py(ri.globalenv.get(output)) else: output_ipy = localconverter.ri2py(ri.globalenv.get(output)) self.shell.push({output: output_ipy }) # this will keep a reference to the display_data # which might be useful to other objects who happen to use # this method if self.cache_display_data: self.display_cache = display_data # We're in line mode and return_output is still True, # so return the converted result if return_output and not args.noreturn: if result is not ri.NULL: if args.converter is None: return converter.ri2py(result) else: return localconverter.ri2py(result)