def _showfiles(nfiles: int, files, headers, wtitle, delete, pager) -> int: filenames = [] headers_str = [] wtitle_str = None pager_str = None try: wtitle_str = conversion._cchar_to_str(wtitle, _CCHAR_ENCODING) pager_str = conversion._cchar_to_str(pager, _CCHAR_ENCODING) for i in range(nfiles): filenames.append( conversion._cchar_to_str(files[i], _CCHAR_ENCODING)) headers_str.append( conversion._cchar_to_str(headers[i], _CCHAR_ENCODING)) except Exception as e: logger.error(_SHOWFILE_INTERNAL_EXCEPTION_LOG, str(e)) if len(filenames): res = 0 else: res = 1 try: showfiles(tuple(filenames), tuple(headers_str), wtitle_str, pager_str) except Exception as e: res = 1 logger.error(_SHOWFILE_EXCEPTION_LOG, str(e)) return res
def _consoleread(prompt, buf, n: int, addtohistory) -> int: success = None try: s = conversion._cchar_to_str(prompt, _CCHAR_ENCODING) reply = consoleread(s) except Exception as e: success = 0 logger.error(_READCONSOLE_EXCEPTION_LOG, str(e)) if success == 0: return success try: # TODO: Should the coding be dynamically extracted from # elsewhere ? reply_b = reply.encode('utf-8') reply_n = min(n, len(reply_b)) pybuf = bytearray(n) pybuf[:reply_n] = reply_b[:reply_n] pybuf[reply_n] = ord('\n') pybuf[reply_n + 1] = 0 openrlib.ffi.memmove(buf, pybuf, n) if reply_n == 0: success = 0 else: success = 1 except Exception as e: success = 0 logger.error(_READCONSOLE_INTERNAL_EXCEPTION_LOG, str(e)) return success
def _yesnocancel(question): try: q = conversion._cchar_to_str(question, _CCHAR_ENCODING) res = yesnocancel(q) except Exception as e: logger.error(_YESNOCANCEL_EXCEPTION_LOG, str(e)) return res
def _string_getitem(cdata: FFI.CData, i: int) -> typing.Optional[str]: elt = openrlib.rlib.STRING_ELT(cdata, i) if elt == openrlib.rlib.R_NaString: res = None else: res = conversion._cchar_to_str(openrlib.rlib.R_CHAR(elt)) return res
def rclass_get(scaps: _rinterface.CapsuleBase) -> StrSexpVector: """ Get the R class name. If no specific attribute "class" is defined from the objects, this will perform the equivalent of R_data_class() (src/main/attrib.c in the R source code). """ 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: classname: typing.Tuple[str, ...] dim = rmemory.protect( rlib.Rf_getAttrib(scaps._cdata, rlib.R_DimSymbol)) ndim = rlib.Rf_length(dim) if ndim > 0: if ndim == 2: if int(RVersion()['major']) >= 4: classname = ('matrix', 'array') else: classname = ('matrix', ) else: classname = ('array', ) else: typeof = RTYPES(scaps.typeof) if typeof in (RTYPES.CLOSXP, RTYPES.SPECIALSXP, RTYPES.BUILTINSXP): classname = ('function', ) elif typeof == RTYPES.REALSXP: classname = ('numeric', ) elif typeof == RTYPES.SYMSXP: classname = ('name', ) elif typeof == RTYPES.LANGSXP: symb = rlib.CAR(scaps._cdata) if openrlib.rlib.Rf_isSymbol(symb): symb_rstr = openrlib.rlib.PRINTNAME(symb) symb_str = conversion._cchar_to_str( openrlib.rlib.R_CHAR(symb_rstr), conversion._R_ENC_PY[openrlib.rlib .Rf_getCharCE(symb_rstr)] ) if symb_str in ('if', 'while', 'for', '=', '<-', '(', '{'): classname = (symb_str, ) else: classname = ('call', ) else: classname = ('call', ) else: classname = (_TYPE2STR.get(typeof, str(typeof)), ) classes = StrSexpVector.from_iterable(classname) else: classes = conversion._cdata_to_rinterface(classes) return classes
def _evaluate_in_r(rargs: FFI.CData) -> FFI.CData: # An uncaught exception in the boby of this function would # result in a segfault. we wrap it in a try-except an report # exceptions as logs. rlib = openrlib.rlib try: rargs = rlib.CDR(rargs) cdata = rlib.CAR(rargs) if (_TYPEOF(cdata) != rlib.EXTPTRSXP): # TODO: also check tag # (rlib.R_ExternalPtrTag(sexp) == '.Python') logger.error('The fist item is not an R external pointer.') return rlib.R_NilValue handle = rlib.R_ExternalPtrAddr(cdata) func = ffi.from_handle(handle) pyargs = [] pykwargs = {} rargs = rlib.CDR(rargs) while rargs != rlib.R_NilValue: cdata = rlib.CAR(rargs) if rlib.Rf_isNull(rlib.TAG(rargs)): # Unnamed argument pyargs.append(conversion._cdata_to_rinterface(cdata)) else: # Named arguments rname = rlib.PRINTNAME(rlib.TAG(rargs)) name = conversion._cchar_to_str( rlib.R_CHAR(rname), conversion._R_ENC_PY[openrlib.rlib.Rf_getCharCE(rname)]) pykwargs[name] = conversion._cdata_to_rinterface(cdata) rargs = rlib.CDR(rargs) res = func(*pyargs, **pykwargs) # The object is whatever the "rternalized" function `func` # is returning and we need to cast that result into a SEXP # that R's C API can handle. At the same time we need to ensure # that the R is: # - protected from garbage collection long enough to let the R # code that called the rternalized function complete. # - eventually its memory is freed to prevent a leak. # To that end, we create a SEXP object to be returned that is # not managed by rpy2, leaving the object's lifespan under R's # sole control. if (hasattr(res, '_sexpobject') and isinstance(res._sexpobject, SexpCapsule)): return res._sexpobject._cdata else: return conversion._python_to_cdata(res) except Exception as e: logger.error('%s: %s' % (type(e), e)) return rlib.R_NilValue
def __str__(self) -> str: return conversion._cchar_to_str( openrlib._STRING_VALUE(self._sexpobject._cdata))
def _showmessage(buf): s = conversion._cchar_to_str(buf, _CCHAR_ENCODING) try: showmessage(s) except Exception as e: logger.error(_SHOWMESSAGE_EXCEPTION_LOG, str(e))