def _remove(name: FFI.CData, env: FFI.CData, inherits) -> FFI.CData: rlib = openrlib.rlib with memorymanagement.rmemory() as rmemory: internal = rmemory.protect( rlib.Rf_install(conversion._str_to_cchar('.Internal'))) remove = rmemory.protect( rlib.Rf_install(conversion._str_to_cchar('remove'))) args = rmemory.protect(rlib.Rf_lang4(remove, name, env, inherits)) call = rmemory.protect(rlib.Rf_lang2(internal, args)) # TODO: use tryEval instead and catch errors. res = rlib.Rf_eval(call, rlib.R_GlobalEnv) return res
def do_slot_assign(self, name: str, value) -> None: _rinterface._assert_valid_slotname(name) cchar = conversion._str_to_cchar(name) with memorymanagement.rmemory() as rmemory: name_r = rmemory.protect(openrlib.rlib.Rf_install(cchar)) cdata = rmemory.protect(conversion._get_cdata(value)) openrlib.rlib.R_do_slot_assign(self.__sexp__._cdata, name_r, cdata)
def find(self, key: str, wantfun: int = False) -> Sexp: """Find an item, starting with this R environment. Raises a `KeyError` is the key cannot be found.""" if not isinstance(key, str): raise TypeError('The key must be a non-empty string.') elif not len(key): raise ValueError('The key must be a non-empty string.') with memorymanagement.rmemory() as rmemory: symbol = rmemory.protect( openrlib.rlib.Rf_install(conversion._str_to_cchar(key))) if wantfun: # One would expect this to be like # res = _rinterface._findfun(symbol, self.__sexp__._cdata) # but R's findfun will segfault if the symbol is not in # the environment. :/ rho = self while rho.rid != emptyenv.rid: res = _rinterface._findVarInFrame(symbol, rho.__sexp__._cdata) if _rinterface._TYPEOF(res) in (openrlib.rlib.CLOSXP, openrlib.rlib.BUILTINSXP): break # TODO: move check of R_UnboundValue to _rinterface ? res = openrlib.rlib.R_UnboundValue rho = rho.enclos else: res = _rinterface._findvar(symbol, self.__sexp__._cdata) # TODO: move check of R_UnboundValue to _rinterface ? if res == openrlib.rlib.R_UnboundValue: raise KeyError("'%s' not found" % key) return res
def do_slot(self, name: str) -> None: _rinterface._assert_valid_slotname(name) cchar = conversion._str_to_cchar(name) with memorymanagement.rmemory() as rmemory: name_r = rmemory.protect(openrlib.rlib.Rf_install(cchar)) if not _rinterface._has_slot(self.__sexp__._cdata, name_r): raise LookupError(name) res = openrlib.rlib.R_do_slot(self.__sexp__._cdata, name_r) return res
def _geterrmessage() -> str: rlib = openrlib.rlib # TODO: use isString and installTrChar with memorymanagement.rmemory() as rmemory: symbol = rmemory.protect( rlib.Rf_install(conversion._str_to_cchar('geterrmessage'))) geterrmessage = _findvar(symbol, rlib.R_GlobalEnv) call_r = rlib.Rf_lang1(geterrmessage) res = rmemory.protect(rlib.Rf_eval(call_r, rlib.R_GlobalEnv)) res = _string_getitem(res, 0) return res
def __getitem__(self, key: str) -> typing.Any: if not (isinstance(key, str) and len(key)): raise ValueError('The key must be a non-empty string.') with memorymanagement.rmemory() as rmemory: symbol = rmemory.protect( openrlib.rlib.Rf_install(conversion._str_to_cchar(key))) res = _rinterface._findVarInFrame(symbol, self.__sexp__._cdata) # TODO: move check of R_UnboundValue to _rinterface if res == openrlib.rlib.R_UnboundValue: raise KeyError("'%s' not found" % key) return res
def _choosefile(new, buf, n: int) -> int: try: res = choosefile(new) except Exception as e: logger.error(_CHOOSEFILE_EXCEPTION_LOG, str(e)) res = None if res is None: return 0 res_cdata = conversion._str_to_cchar(res) openrlib.ffi.memmove(buf, res_cdata, len(res_cdata)) return len(res_cdata)
def __setitem__(self, key: str, value) -> None: # TODO: move body to _rinterface-level function if not (isinstance(key, str) and len(key)): raise ValueError('The key must be a non-empty string.') if (self.__sexp__._cdata == openrlib.rlib.R_BaseEnv) or \ (self.__sexp__._cdata == openrlib.rlib.R_EmptyEnv): raise ValueError('Cannot remove variables from the base or ' 'empty environments.') # TODO: call to Rf_duplicate needed ? with memorymanagement.rmemory() as rmemory: symbol = rmemory.protect( openrlib.rlib.Rf_install(conversion._str_to_cchar(key))) cdata = rmemory.protect(conversion._get_cdata(value)) cdata_copy = rmemory.protect(openrlib.rlib.Rf_duplicate(cdata)) openrlib.rlib.Rf_defineVar(symbol, cdata_copy, self.__sexp__._cdata)
def __getitem__(self, key: str) -> typing.Any: if not isinstance(key, str): raise TypeError('The key must be a non-empty string.') elif not len(key): raise ValueError('The key must be a non-empty string.') with memorymanagement.rmemory() as rmemory: key_cchar = conversion._str_to_cchar(key) symbol = rmemory.protect(openrlib.rlib.Rf_install(key_cchar)) res = rmemory.protect( _rinterface.findvar_in_frame_wrap(self.__sexp__._cdata, symbol)) # TODO: move check of R_UnboundValue to _rinterface if res == openrlib.rlib.R_UnboundValue: raise KeyError("'%s' not found" % key) return res
def find(self, key: str, wantfun: bool = False) -> Sexp: """Find an item, starting with this R environment. Raises a `KeyError` if the key cannot be found. This method is called `find` because it is somewhat different from the method :meth:`get` in Python mappings such :class:`dict`. This is looking for a key across enclosing environments, returning the first key found.""" if not isinstance(key, str): raise TypeError('The key must be a non-empty string.') elif not len(key): raise ValueError('The key must be a non-empty string.') with memorymanagement.rmemory() as rmemory: key_cchar = conversion._str_to_cchar(key, 'utf-8') symbol = rmemory.protect( openrlib.rlib.Rf_install(key_cchar) ) if wantfun: # One would expect this to be like # res = _rinterface._findfun(symbol, self.__sexp__._cdata) # but R's findfun will segfault if the symbol is not in # the environment. :/ rho = self while rho.rid != emptyenv.rid: res = rmemory.protect( _rinterface.findvar_in_frame_wrap( rho.__sexp__._cdata, symbol ) ) if _rinterface._TYPEOF(res) in (openrlib.rlib.CLOSXP, openrlib.rlib.BUILTINSXP): break # TODO: move check of R_UnboundValue to _rinterface ? res = openrlib.rlib.R_UnboundValue rho = rho.enclos else: res = _rinterface._findvar(symbol, self.__sexp__._cdata) # TODO: move check of R_UnboundValue to _rinterface ? if res == openrlib.rlib.R_UnboundValue: raise KeyError("'%s' not found" % key) return res
def __delitem__(self, key: str) -> None: # Testing that key is a non-empty string is implicitly # performed when checking that the key is in the environment. if key not in self: raise KeyError("'%s' not found" % key) if self.__sexp__ == baseenv.__sexp__: raise ValueError('Values from the R base environment ' 'cannot be removed.') # TODO: also check it is not R_EmpyEnv or R_BaseNamespace if self.is_locked(): ValueError('Cannot remove an item from a locked ' 'environment.') with memorymanagement.rmemory() as rmemory: key_cdata = rmemory.protect( openrlib.rlib.Rf_mkString(conversion._str_to_cchar(key))) _rinterface._remove( key_cdata, self.__sexp__._cdata, openrlib.rlib.Rf_ScalarLogical(openrlib.rlib.FALSE))
def unserialize(cdata: FFI.CData, cdata_env: FFI.CData) -> FFI.CData: """Unserialize an R string to an R object. Note that the R object returned is *not* protected from the R garbage collection.""" rlib = openrlib.rlib with memorymanagement.rmemory() as rmemory: sym_unserialize = rmemory.protect( rlib.Rf_install(conversion._str_to_cchar('unserialize'))) func_unserialize = rmemory.protect( _findfun(sym_unserialize, rlib.R_BaseEnv)) r_call = rmemory.protect(rlib.Rf_lang2(func_unserialize, cdata)) error_occured = ffi.new('int *', 0) res = rlib.R_tryEval(r_call, cdata_env, error_occured) if error_occured[0]: raise embedded.RRuntimeError(_geterrmessage()) return res
def build_rcall(rfunction, args=[], kwargs=[]): rlib = openrlib.rlib with memorymanagement.rmemory() as rmemory: rcall = rmemory.protect(rlib.Rf_allocList(len(args) + len(kwargs) + 1)) _SET_TYPEOF(rcall, rlib.LANGSXP) rlib.SETCAR(rcall, rfunction) item = rlib.CDR(rcall) for val in args: cdata = rmemory.protect(conversion._get_cdata(val)) rlib.SETCAR(item, cdata) item = rlib.CDR(item) for key, val in kwargs: if key is not None: _assert_valid_slotname(key) rlib.SET_TAG(item, rlib.Rf_install(conversion._str_to_cchar(key))) cdata = rmemory.protect(conversion._get_cdata(val)) rlib.SETCAR(item, cdata) item = rlib.CDR(item) return rcall