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 __getitem__(self, i: Union[int, slice]) -> Sexp: cdata = self.__sexp__._cdata rlib = openrlib.rlib if isinstance(i, int): # R-exts says that it is converted to a VECSXP when subsetted. i_c = _rinterface._python_index_to_c(cdata, i) item_cdata = rlib.Rf_nthcdr(cdata, i_c) with memorymanagement.rmemory() as rmemory: res_cdata = rmemory.protect( rlib.Rf_allocVector(RTYPES.VECSXP, 1)) rlib.SET_VECTOR_ELT( res_cdata, 0, rlib.CAR( item_cdata )) res_name = rmemory.protect( rlib.Rf_allocVector(RTYPES.STRSXP, 1)) item_cdata_name = rlib.PRINTNAME(rlib.TAG(item_cdata)) if _rinterface._TYPEOF(item_cdata_name) != rlib.NILSXP: rlib.SET_STRING_ELT( res_name, 0, item_cdata_name) rlib.Rf_namesgets(res_cdata, res_name) res = conversion._cdata_to_rinterface(res_cdata) elif isinstance(i, slice): iter_indices = range(*i.indices(len(self))) n = len(iter_indices) with memorymanagement.rmemory() as rmemory: res_cdata = rmemory.protect( rlib.Rf_allocVector( self._R_TYPE, n) ) iter_res_cdata = res_cdata prev_i = 0 lst_cdata = self.__sexp__._cdata for i in iter_indices: if i >= len(self): raise IndexError('index out of range') lst_cdata = rlib.Rf_nthcdr(lst_cdata, i - prev_i) prev_i = i rlib.SETCAR(iter_res_cdata, rlib.CAR(lst_cdata)) rlib.SET_TAG(iter_res_cdata, rlib.TAG(lst_cdata)) iter_res_cdata = rlib.CDR(iter_res_cdata) res = conversion._cdata_to_rinterface(res_cdata) else: raise TypeError( 'Indices must be integers or slices, not %s' % type(i)) 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 typeof(self) -> RTYPES: return RTYPES(_rinterface._TYPEOF(self.__sexp__._cdata))