def fetch(self, key): """ Fetch the documentation page associated with a given key. - for S4 classes, the class name is *often* prefixed with 'class.'. For example, the key to the documentation for the class AnnotatedDataFrame in the package Biobase is 'class.AnnotatedDataFrame'. """ rdx_variables = self._rdx.rx2('variables') if key not in rdx_variables.names: raise HelpNotFoundError("No help could be fetched", topic=key, package=self.__package_name) rkey = StrSexpVector(rinterface.StrSexpVector((key, ))) rpath = StrSexpVector((os.path.join(self.package_path, 'help', self.__package_name + '.rdb'),)) _eval = rinterface.baseenv['eval'] devnull_func = rinterface.parse('function(x) {}') devnull_func = _eval(devnull_func) res = lazyload_dbfetch(rdx_variables.rx(rkey)[0], rpath, self._rdx.rx2("compressed"), devnull_func) p_res = Page(res) return p_res
def testMissingArg(self): exp = rinterface.parse("function(x) { missing(x) }") fun = rinterface.baseenv["eval"](exp) nonmissing = rinterface.SexpVector([0, ], rinterface.INTSXP) missing = rinterface.MissingArg self.assertEqual(False, fun(nonmissing)[0]) self.assertEqual(True, fun(missing)[0])
def fetch(self, alias): """ Fetch the documentation page associated with a given alias. For S4 classes, the class name is *often* suffixed with '-class'. For example, the alias to the documentation for the class AnnotatedDataFrame in the package Biobase is 'AnnotatedDataFrame-class'. """ c = self._dbcon.execute('SELECT rd_meta_rowid, alias FROM rd_alias_meta WHERE alias=?', (alias, )) res_alias = c.fetchall() if len(res_alias) == 0: raise HelpNotFoundError("No help could be fetched", topic = alias, package = self.__package_name) c = self._dbcon.execute('SELECT file, name, type FROM rd_meta WHERE rowid=?', (res_alias[0][0], )) # since the selection is on a verified rowid we are sure to exactly get one row res = c.fetchall() rkey = StrSexpVector((res[0][0][:-3], )) _type = res[0][2] rpath = StrSexpVector((os.path.join(self.package_path, 'help', self.__package_name + '.rdb'),)) rdx_variables = self._rdx[self._rdx.do_slot('names').index('variables')] _eval = rinterface.baseenv['eval'] devnull_func = rinterface.parse('function(x) {}') devnull_func = _eval(devnull_func) res = _lazyload_dbfetch(rdx_variables[rdx_variables.do_slot('names').index(rkey[0])], rpath, self._rdx[self._rdx.do_slot('names').index("compressed")], devnull_func) p_res = Page(res, _type = _type) return p_res
def fetch(self, key): """ Fetch the documentation page associated with a given key. - for S4 classes, the class name is *often* prefixed with 'class.'. For example, the key to the documentation for the class AnnotatedDataFrame in the package Biobase is 'class.AnnotatedDataFrame'. """ rdx_variables = self._rdx.rx2('variables') if key not in rdx_variables.names: raise HelpNotFoundError("No help could be fetched", topic=key, package=self.__package_name) rkey = StrSexpVector(rinterface.StrSexpVector((key, ))) rpath = StrSexpVector((os.path.join(self.package_path, 'help', self.__package_name + '.rdb'), )) _eval = rinterface.baseenv['eval'] devnull_func = rinterface.parse('function(x) {}') devnull_func = _eval(devnull_func) res = lazyload_dbfetch( rdx_variables.rx(rkey)[0], rpath, self._rdx.rx2("compressed"), devnull_func) p_res = Page(res) return p_res
def eval(self, line): # self.output.append(line + '\n') try: ri.baseenv['eval'](ri.parse(line)) except ri.RRuntimeError as msg: self.output.append('ERROR parsing "%s": %s\n' % (line, msg)) pass
def eval(self, line): """Evaluate a line or block of code in R Parameters ---------- line : str The code to execute Examples -------- >>> r.eval(''' ... x = 1:5 ... df = data.frame(x=x, y=x^2) ... print(df) ... ''') x y 1 1 1 2 2 4 3 3 9 4 4 16 5 5 25 """ old_writeconsole = ri.get_writeconsole() ri.set_writeconsole(self._write_console) try: value = ri.baseenv['eval'](ri.parse(line)) 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) text_output = self._flush() ri.set_writeconsole(old_writeconsole) if text_output: sys.stdout.write(unicode_to_str(text_output, 'utf-8'))
def quiet_require(name, lib_loc=None): """ Load an R package /quietly/ (suppressing messages to the console). """ if lib_loc == None: lib_loc = "NULL" expr_txt = "suppressPackageStartupMessages(base::require(%s, lib.loc=%s))" \ %(name, lib_loc) expr = rinterface.parse(expr_txt) ok = _eval(expr) return ok
def reval(string, envir = _globalenv): """ Evaluate a string as R code - string: a string - envir: an environment in which the environment should take place (default: R's global environment) """ p = rinterface.parse(string) res = _reval(p, envir = envir) return res
def quiet_require(name, lib_loc = None): """ Load an R package /quietly/ (suppressing messages to the console). """ if lib_loc == None: lib_loc = "NULL" expr_txt = "suppressPackageStartupMessages(base::require(%s, lib.loc=%s))" \ %(name, lib_loc) expr = rinterface.parse(expr_txt) ok = _eval(expr) return ok
def quiet_require(name: str, lib_loc: typing.Optional[str] = None) -> bool: """ Load an R package /quietly/ (suppressing messages to the console). """ if lib_loc is None: lib_loc = "NULL" expr_txt = ('suppressPackageStartupMessages(base::require(%s, lib.loc=%s))' % (name, lib_loc)) expr = rinterface.parse(expr_txt) ok = _eval(expr) return ok
def run_r_script(script_name, inputs, outputs): """ Executes the specified R script Parameters : - script_name is the name of the script we should execute - inputs is a dict containing PredictionValue instances. Before the script gets executed, each entry in the dict will be injected into the R environment as variables (the dict key being the variable name). - outputs is a dict, whick contains one key per variable that should be read from the R environment after the script gets executed. When the R script is done the method will copy values from the R variables to this dict. Note that since R internally represent scalars as lists, all scalar values will be returned as lists with one element. The function returns True upon successful completion, or False if something went wrong. """ # We import R at function level so that we load one R environment per # call. This way we make it possible to call several R scripts simultaneously # on separated threads without risking to break the R environment import rpy2.rinterface as ri from rpy2.robjects.packages import importr ri.initr() r_base = importr('base') with open(script_name, 'r') as r_file: script = r_file.read() try: r_expr = ri.parse(script) except Exception as ex: logging.error( 'An error occured while parsing an R script "{0}": {1}'.format( script_name, ex.message)) return False # Inject inputs into R for key, value in inputs.iteritems(): ri.globalenv[key] = PredictionWorker.__value_py_to_r(value, ri) # Execute try: r_base.eval(r_expr) except Exception as ex: logging.error( 'An error occured while executing the R script "{0}": {1}'. format(script_name, ex.message)) logging.debug('Inputs:') for ikey, ival in inputs.iteritems(): logging.debug('{0}: {1}'.format(ikey, ival)) return False # Read outputs for key in outputs.iterkeys(): outputs[key] = PredictionWorker.__value_r_to_py( ri.globalenv[key], ri) return True
def test_missing_arg(): exp = rinterface.parse('function(x) { missing(x) }') fun = rinterface.baseenv['eval'](exp) nonmissing = rinterface.IntSexpVector([ 0, ]) missing = rinterface.MissingArg assert not fun(nonmissing)[0] assert fun(missing)[0]
def reval(string, envir=_globalenv): """ Evaluate a string as R code :param string: R code :type string: a :class:`str` :param envir: an environment in which the environment should take place (default: R's global environment) """ p = rinterface.parse(string) res = _reval(p, envir=envir) return res
def testMissingArg(self): exp = rinterface.parse("function(x) { missing(x) }") fun = rinterface.baseenv["eval"](exp) nonmissing = rinterface.SexpVector([ 0, ], rinterface.INTSXP) missing = rinterface.MissingArg self.assertEqual(False, fun(nonmissing)[0]) self.assertEqual(True, fun(missing)[0])
def reval(string: str, envir: typing.Optional[rinterface.SexpEnvironment] = None): """ Evaluate a string as R code :param string: R code :type string: a :class:`str` :param envir: Optional environment to evaluate the R code. """ p = rinterface.parse(string) res = _reval(p, envir=envir) return res
def testRcallOrdDictEnv(self): ad = rlc.OrdDict(((None, rinterface.parse('sum(x)')), )) env_a = rinterface.baseenv['new.env']() env_a['x'] = rinterface.IntSexpVector([1, 2, 3]) sum_a = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_a) self.assertEqual(6, sum_a[0]) env_b = rinterface.baseenv['new.env']() env_b['x'] = rinterface.IntSexpVector([4, 5, 6]) sum_b = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_b) self.assertEqual(15, sum_b[0])
def test_call_OrdDictEnv(): ad = rlc.OrdDict(((None, rinterface.parse('sum(x)')), )) env_a = rinterface.baseenv['new.env']() env_a['x'] = rinterface.IntSexpVector([1, 2, 3]) sum_a = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_a) assert 6 == sum_a[0] env_b = rinterface.baseenv['new.env']() env_b['x'] = rinterface.IntSexpVector([4, 5, 6]) sum_b = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_b) assert 15 == sum_b[0]
def quiet_require(name, lib_loc=None): """ Load an R package /quietly/ (suppressing messages to the console). """ if lib_loc is None: lib_loc = "NULL" else: lib_loc = "\"%s\"" % (lib_loc.replace('"', '\\"')) expr_txt = ("suppressPackageStartupMessages(" "base::require(%s, lib.loc=%s))" % (name, lib_loc)) expr = rinterface.parse(expr_txt) ok = _eval_quiet(expr) return ok
def testRcallOrdDictEnv(self): ad = rlc.OrdDict( ((None, rinterface.parse('sum(x)')),) ) env_a = rinterface.baseenv['new.env']() env_a['x'] = rinterface.IntSexpVector([1,2,3]) sum_a = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_a) self.assertEqual(6, sum_a[0]) env_b = rinterface.baseenv['new.env']() env_b['x'] = rinterface.IntSexpVector([4,5,6]) sum_b = rinterface.baseenv['eval'].rcall(tuple(ad.items()), env_b) self.assertEqual(15, sum_b[0])
def testSetResetConsole(self): reset = [0] def f(): reset[0] += 1 rinterface.set_resetconsole(f) self.assertEqual(rinterface.get_resetconsole(), f) try: rinterface.baseenv['eval'](rinterface.parse('1+"a"')) except rinterface.RRuntimeError: pass self.assertEqual(1, reset[0])
def testSetResetConsole(self): reset = [0] def f(): reset[0] += 1 rinterface.set_resetconsole(f) self.assertEqual(rinterface.get_resetconsole(), f) with self.assertRaises(rinterface.RRuntimeError): with pytest.warns(rinterface.RRuntimeWarning): rinterface.baseenv['eval'](rinterface.parse('1+"a"')) self.assertEqual(1, reset[0])
def testClosureenv(self): exp = rinterface.parse("function(x) { x[y] }") fun = rinterface.baseenv["eval"](exp) vec = rinterface.baseenv["letters"] self.assertRaises(rinterface.RRuntimeError, fun, vec) fun.closureenv()["y"] = rinterface.SexpVector([1, ], rinterface.INTSXP) self.assertEqual('a', fun(vec)[0]) fun.closureenv()["y"] = rinterface.SexpVector([2, ], rinterface.INTSXP) self.assertEqual('b', fun(vec)[0])
def testClosureenv(self): exp = rinterface.parse("function(x) { x[y] }") fun = rinterface.baseenv["eval"](exp) vec = rinterface.baseenv["letters"] self.assertRaises(rinterface.RRuntimeError, fun, vec) fun.closureenv["y"] = rinterface.SexpVector([ 1, ], rinterface.INTSXP) self.assertEqual('a', fun(vec)[0]) fun.closureenv["y"] = rinterface.SexpVector([ 2, ], rinterface.INTSXP) self.assertEqual('b', fun(vec)[0])
def eval(self, line): ''' Parse and evaluate a line with rpy2. Returns the output to R's stdout() connection and the value of eval(parse(line)). ''' old_writeconsole = ri.get_writeconsole() ri.set_writeconsole(self.write_console) try: value = ri.baseenv['eval'](ri.parse(line)) 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) text_output = self.flush() ri.set_writeconsole(old_writeconsole) return text_output, value
def eval(self, line): ''' Parse and evaluate a line with rpy2. Returns the output to R's stdout() connection and the value of eval(parse(line)). ''' old_writeconsole = ri.get_writeconsole() ri.set_writeconsole(self.write_console) try: value = ri.baseenv['eval'](ri.parse(line)) except (ri.RRuntimeError, ValueError) as exception: warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error raise RMagicError(unicode_to_str('parsing and evaluating line "%s".\nR error message: "%s"\n R stdout:"%s"\n' % (line, str_to_unicode(exception.message, 'utf-8'), warning_or_other_msg))) text_output = self.flush() ri.set_writeconsole(old_writeconsole) return text_output, value
def eval(self, line): ''' Parse and evaluate a line with rpy2. Returns the output to R's stdout() connection and the value of eval(parse(line)). ''' old_writeconsole = ri.get_writeconsole() ri.set_writeconsole(self.write_console) try: value = ri.baseenv['eval'](ri.parse(line)) 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) text_output = self.flush() ri.set_writeconsole(old_writeconsole) return text_output, value
def testClosureenv(self): if 'y' in rinterface.globalenv: del (rinterface.globalenv['y']) exp = rinterface.parse('function(x) { x[y] }') fun = rinterface.baseenv['eval'](exp) vec = rinterface.baseenv['letters'] with self.assertRaises(rinterface.RRuntimeError): with pytest.warns(rinterface.RRuntimeWarning): fun(vec) fun.closureenv['y'] = (rinterface.SexpVector([ 1, ], rinterface.INTSXP)) self.assertEqual('a', fun(vec)[0]) fun.closureenv['y'] = (rinterface.SexpVector([ 2, ], rinterface.INTSXP)) self.assertEqual('b', fun(vec)[0])
def test_closureenv(): assert 'y' not in rinterface.globalenv exp = rinterface.parse('function(x) { x[y] }') fun = rinterface.baseenv['eval'](exp) vec = rinterface.baseenv['letters'] assert isinstance(fun.closureenv, rinterface.SexpEnvironment) with pytest.raises(rinterface.embedded.RRuntimeError): with pytest.warns(rinterface.RRuntimeWarning): fun(vec) fun.closureenv['y'] = (rinterface.IntSexpVector([ 1, ])) assert 'a' == fun(vec)[0] fun.closureenv['y'] = (rinterface.IntSexpVector([ 2, ])) assert 'b' == fun(vec)[0]
def as_symbol(x): res = rinterface.parse(x) return res
import rpy2.rinterface as rinterface _reval = rinterface.baseenv['eval'] # NULL NULL = _reval(rinterface.parse("NULL")) # TRUE/FALSE TRUE = _reval(rinterface.parse("TRUE")) FALSE = _reval(rinterface.parse("FALSE"))
def cell_magic(self, args, text): # need to get the ipython instance for assigning opts, args = getopt(args.strip().split(' '), None, ['inputs=', 'outputs=', # these are options for png 'width=', 'height=', 'units=', 'pointsize=', 'bg=']) opts = dict(opts) outputs = [] for option, value in opts.items(): if option == '--inputs': # need to have access the shell to assign these # python variables to variables in R opts.pop('--inputs') # with self.shell, we will assign the values to variables in the shell # for now, this is a hack, with self.shell a dictionary for input in value.split(','): self.r.assign(input, self.shell[input]) if option == '--outputs': outputs = value.split(',') opts.pop('--outputs') png_args = ','.join(['%s=%s' % (o[2:],v) for o, v in opts.items()]) # execute the R code in a temporary directory tmpd = tempfile.mkdtemp() self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd, png_args)) self.eval(ri.parse(text)) self.r('dev.off()') # read out all the saved .png files images = [file(imgfile).read() for imgfile in glob("%s/Rplots*png" % tmpd)] # now publish the images # mimicking IPython/zmq/pylab/backend_inline.py fmt = 'png' mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' } mime = mimetypes[fmt] # publish the printed R objects, if any publish_display_data('Rmagic.cell_magic', {'text/plain':self.flush()}) # flush text streams before sending figures, helps a little with output for image in images: # synchronization in the console (though it's a bandaid, not a real sln) sys.stdout.flush(); sys.stderr.flush() publish_display_data( 'Rmagic.cell_magic', {mime : image} ) value = {} # try to turn every output into a numpy array # this means that outputs are assumed to be castable # as numpy arrays for output in outputs: # with self.shell, we will assign the values to variables in the shell self.shell[output] = np.asarray(self.r(output)) # kill the temporary directory rmtree(tmpd)
def test_parse_error_when_evaluting(): with pytest.raises(_rinterface.RParsingError): rinterface.parse("list(''=1)")
def testParse(self): xp = rinterface.parse("2 + 3") self.assertEqual(rinterface.EXPRSXP, xp.typeof) self.assertEqual(2.0, xp[0][1][0]) self.assertEqual(3.0, xp[0][2][0])
def test_parse_invalid_string(): with pytest.raises(TypeError): rinterface.parse(3)
def parse(self): if self._parsed is None: self._parsed = ParsedCode(rinterface.parse(self)) return self._parsed
def testParseUnicode(self): xp = rinterface.parse(u'"\u21a7"') self.assertEqual(1, len(xp)) self.assertEqual(1, len(xp[0]))
def test_parse_error(): with pytest.raises(_rinterface.RParsingError): rinterface.parse("2 + 3 , 1")
def __call__(self, string): p = rinterface.parse(string) res = self.eval(p) return res
def test_parse_ok(): xp = rinterface.parse('2 + 3') assert xp.typeof == rinterface.RTYPES.EXPRSXP assert 2.0 == xp[0][1][0] assert 3.0 == xp[0][2][0]
def test_parse_incomplete_error(): with pytest.raises(_rinterface.RParsingError) as rpe: rinterface.parse("2 + 3 /") assert rpe.value.status == (_rinterface.PARSING_STATUS.PARSE_INCOMPLETE)
def test_parse_unicode(): xp = rinterface.parse(u'"\u21a7"') assert len(xp) == 1 assert len(xp[0]) == 1
""" R objects with fixed values. """ import rpy2.rinterface as rinterface _reval = rinterface.baseenv['eval'] # NULL NULL = _reval(rinterface.parse("NULL")) # TRUE/FALSE TRUE = _reval(rinterface.parse("TRUE")) FALSE = _reval(rinterface.parse("FALSE"))
from rpy2.robjects.robject import RObjectMixin, RObject import rpy2.rinterface as rinterface #import rpy2.robjects.conversion as conversion import conversion baseenv_ri = rinterface.baseenv #needed to avoid circular imports _reval = rinterface.baseenv['eval'] NULL = _reval(rinterface.parse("NULL")) class Function(RObjectMixin, rinterface.SexpClosure): """ Python representation of an R function. """ __formals = baseenv_ri.get('formals') __local = baseenv_ri.get('local') __call = baseenv_ri.get('call') __assymbol = baseenv_ri.get('as.symbol') __newenv = baseenv_ri.get('new.env') _local_env = None def __init__(self, *args, **kwargs): super(Function, self).__init__(*args, **kwargs) self._local_env = self.__newenv(hash=rinterface.BoolSexpVector((True, ))) def __call__(self, *args, **kwargs): new_args = [conversion.py2ri(a) for a in args] new_kwargs = {}
def evalr(string): res = ri.parse(string) res = ri.baseenv["eval"](res) return res
def cell_magic(self, args, text): ''' A cell-level magic for R. Parameters ---------- args: {inputs, outputs, width, height, units, pointsize, bg} Optional long arguments recognized by the cell magic. The first two relate to passing python objects back and forth between rpy2 and python: '--inputs' should be a comma separated list of names of objects in the namespace of the shell; '--outputs' are names of object in the R namespace that are returned as arrays. All other args are passed as arguments to the png plotting device in R. text: str String of R code to be executed by rpy2. Anything written to stdout of R is captured, as are plots (in the form of .png files) that are published via ipython's frontend publishing system. ''' # need to get the ipython instance for assigning opts, args = getopt(args.strip().split(' '), None, ['inputs=', 'outputs=', # these are options for png 'width=', 'height=', 'units=', 'pointsize=', 'bg=']) opts = dict(opts) outputs = [] for option, value in opts.items(): if option == '--inputs': # need to have access the shell to assign these # python variables to variables in R opts.pop('--inputs') # with self.shell, we will assign the values to variables in the shell # for now, this is a hack, with self.shell a dictionary for input in value.split(','): self.r.assign(input, self.shell[input]) if option == '--outputs': outputs = value.split(',') opts.pop('--outputs') png_args = ','.join(['%s=%s' % (o[2:],v) for o, v in opts.items()]) # execute the R code in a temporary directory tmpd = tempfile.mkdtemp() self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd, png_args)) self.eval(ri.parse(text)) self.r('dev.off()') # read out all the saved .png files images = [file(imgfile).read() for imgfile in glob("%s/Rplots*png" % tmpd)] # now publish the images # mimicking IPython/zmq/pylab/backend_inline.py fmt = 'png' mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' } mime = mimetypes[fmt] # publish the printed R objects, if any publish_display_data('Rmagic.cell_magic', {'text/plain':self.flush()}) # flush text streams before sending figures, helps a little with output for image in images: # synchronization in the console (though it's a bandaid, not a real sln) sys.stdout.flush(); sys.stderr.flush() publish_display_data( 'Rmagic.cell_magic', {mime : image} ) value = {} # try to turn every output into a numpy array # this means that outputs are assumed to be castable # as numpy arrays for output in outputs: # with self.shell, we will assign the values to variables in the shell self.shell[output] = np.asarray(self.r(output)) # kill the temporary directory rmtree(tmpd)