コード例 #1
0
def make_extptr(obj, tag, protected):
    if protected is None:
        cdata_protected = openrlib.rlib.R_NilValue
    else:
        try:
            cdata_protected = protected.__sexp__._cdata
        except AttributeError:
            raise TypeError('Argument protected must inherit from %s' %
                            type(Sexp))

    ptr = _rinterface.ffi.new_handle(obj)
    with memorymanagement.rmemory() as rmemory:
        cdata = rmemory.protect(
            openrlib.rlib.R_MakeExternalPtr(ptr, tag, cdata_protected))
        openrlib.rlib.R_RegisterCFinalizer(
            cdata, (_rinterface._capsule_finalizer_c
                    if _rinterface._capsule_finalizer_c else
                    _rinterface._capsule_finalizer))
        res = _rinterface.SexpCapsuleWithPassenger(cdata, obj, ptr)
    return res
コード例 #2
0
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
コード例 #3
0
    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
コード例 #4
0
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
コード例 #5
0
ファイル: rinterface.py プロジェクト: gijzelaerr/rpy2
 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)
コード例 #6
0
 def from_iterable(cls,
                   iterable,
                   populate_func=None,
                   set_elt=None,
                   cast_value=None) -> VT:
     """Create an R vector/array from an iterable."""
     if not embedded.isready():
         raise embedded.RNotReadyError('Embedded R is not ready to use.')
     if populate_func is None:
         populate_func = _populate_r_vector
     if set_elt is None:
         set_elt = cls._R_SET_VECTOR_ELT
     if cast_value is None:
         cast_value = cls._CAST_IN
     n = len(iterable)
     with memorymanagement.rmemory() as rmemory:
         r_vector = rmemory.protect(
             openrlib.rlib.Rf_allocVector(cls._R_TYPE, n))
         populate_func(iterable, r_vector, set_elt, cast_value)
     return r_vector
コード例 #7
0
ファイル: rinterface.py プロジェクト: gijzelaerr/rpy2
    def find(self,
             key: str,
             wantfun: bool = False) -> sexp.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:
            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
コード例 #8
0
def rclass_get(scaps: _rinterface.CapsuleBase) -> StrSexpVector:
    rlib = openrlib.rlib
    with memorymanagement.rmemory() as rmemory:
        classes = rmemory.protect(
            rlib.Rf_getAttrib(scaps._cdata, rlib.R_ClassSymbol))
        if rlib.Rf_length(classes) == 0:
            dim = rmemory.protect(
                rlib.Rf_getAttrib(scaps._cdata, rlib.R_DimSymbol))
            ndim = rlib.Rf_length(dim)
            if ndim > 0:
                if ndim == 2:
                    classname = 'matrix'
                else:
                    classname = 'array'
            else:
                typeof = RTYPES(scaps.typeof)
                classname = _DEFAULT_RCLASS_NAMES.get(typeof, str(typeof))
            classes = StrSexpVector.from_iterable([classname])
        else:
            classes = conversion._cdata_to_rinterface(classes)
    return classes
コード例 #9
0
ファイル: rinterface.py プロジェクト: gijzelaerr/rpy2
    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))
コード例 #10
0
    def from_memoryview(cls, mview: memoryview) -> VT:
        """Create an R vector/array from a memoryview.

        The memoryview must be contiguous, and the C representation
        for the vector must be compatible between R and Python. If
        not the case, a :class:`ValueError` exception with will be
        raised."""
        if not embedded.isready():
            raise embedded.RNotReadyError('Embedded R is not ready to use.')
        if not mview.contiguous:
            raise ValueError('The memory view must be contiguous.')
        if ((mview.itemsize != cls._R_SIZEOF_ELT)
                or not hasattr(cls, '_NP_TYPESTR')
                or not (cls._NP_TYPESTR == '|u1'
                        or cls._NP_TYPESTR.endswith(mview.format))):
            msg = (
                'Incompatible C type sizes. '
                'The R array type is {r_type} with {r_size} byte{r_size_pl} '
                'per item '
                'while the Python array type is {py_type} with {py_size} '
                'byte{py_size_pl} per item.'.format(
                    r_type=cls._R_TYPE,
                    r_size=cls._R_SIZEOF_ELT,
                    r_size_pl='s' if cls._R_SIZEOF_ELT > 1 else '',
                    py_type=mview.format,
                    py_size=mview.itemsize,
                    py_size_pl='s' if mview.itemsize > 1 else ''))
            raise ValueError(msg)
        r_vector = None
        n = len(mview)
        with memorymanagement.rmemory() as rmemory:
            r_vector = rmemory.protect(
                openrlib.rlib.Rf_allocVector(cls._R_TYPE, n))
            dest_ptr = cls._R_GET_PTR(r_vector)
            src_ptr = _rinterface.ffi.from_buffer(mview)
            nbytes = n * mview.itemsize
            _rinterface.ffi.memmove(dest_ptr, src_ptr, nbytes)
        return r_vector
コード例 #11
0
    def rcall(self, keyvals, environment: SexpEnvironment):
        """Call/evaluate an R function.

        Args:
        - keyvals: a sequence of key/value (name/parameter) pairs. A
            name/parameter that is None will indicated an unnamed parameter.
            Like in R, keys/names do not have to be unique, partial matching
            can be used, and named/unnamed parameters can occur at any position
            in the sequence.
        - environment: a R environment in which to evaluate the function.
        """
        # TODO: check keyvals are pairs ?
        assert isinstance(environment, SexpEnvironment)
        error_occured = _rinterface.ffi.new('int *', 0)
        with memorymanagement.rmemory() as rmemory:
            call_r = rmemory.protect(
                _rinterface.build_rcall(self.__sexp__._cdata, [], keyvals))
            res = rmemory.protect(
                openrlib.rlib.R_tryEval(call_r, environment.__sexp__._cdata,
                                        error_occured))
            if error_occured[0]:
                raise embedded.RRuntimeError(_rinterface._geterrmessage())
        return res
コード例 #12
0
    def from_memoryview(cls, mview: memoryview) -> VT:
        """Create an R vector/array from a memoryview.

        The memoryview must be contiguous, and the C representation
        for the vector must be compatible between R and Python. If
        not the case, a :class:`ValueError` exception with will be
        raised."""
        if not embedded.isready():
            raise embedded.RNotReadyError('Embedded R is not ready to use.')
        if not mview.contiguous:
            raise ValueError('The memory view must be contiguous.')
        if not cls._check_C_compatible(mview):
            cls._raise_incompatible_C_size(mview)

        r_vector = None
        n = len(mview)
        with memorymanagement.rmemory() as rmemory:
            r_vector = rmemory.protect(
                openrlib.rlib.Rf_allocVector(cls._R_TYPE, n))
            dest_ptr = cls._R_GET_PTR(r_vector)
            src_ptr = _rinterface.ffi.from_buffer(mview)
            nbytes = n * mview.itemsize
            _rinterface.ffi.memmove(dest_ptr, src_ptr, nbytes)
        return r_vector