1from __future__ import unicode_literals, absolute_import 2from rchitect._cffi import lib 3 4import operator 5import sys 6import importlib 7from six import text_type 8from types import ModuleType 9 10from .interface import rcopy, robject, rfunction, rcall_p, rcall 11 12 13def get_p(name, envir): 14 return rcall_p(("base", "get"), name, envir=envir) 15 16 17def inject_py_tools(): 18 19 def py_import(module): 20 return importlib.import_module(module) 21 22 def py_import_builtins(): 23 if sys.version >= "3": 24 return importlib.import_module("builtins") 25 else: 26 return importlib.import_module("__builtin__") 27 28 def py_call(fun, *args, **kwargs): 29 # todo: suuport .asis and .convert 30 if isinstance(fun, text_type): 31 fun = eval(fun) 32 return fun(*args, **kwargs) 33 34 def py_copy(*args): 35 return robject(*args) 36 37 def py_eval(code): 38 return eval(code) 39 40 def py_get_attr(obj, key): 41 if isinstance(obj, ModuleType): 42 try: 43 return importlib.import_module("{}.{}".format(obj.__name__, key)) 44 except ImportError: 45 pass 46 return getattr(obj, key) 47 48 def py_get_item(obj, key): 49 return obj[key] 50 51 def py_names(obj): 52 try: 53 return list(k for k in obj.__dict__.keys() if not k.startswith("_")) 54 except Exception: 55 return None 56 57 def py_object(*args): 58 if len(args) == 1: 59 return robject("PyObject", rcopy(args[0])) 60 elif len(args) == 2: 61 return robject("PyObject", rcopy(rcopy(object, args[0]), args[1])) 62 63 def py_print(r): 64 rcall_p("cat", repr(r) + "\n") 65 66 def py_set_attr(obj, key, value): 67 lib.Rf_protect(obj) 68 lib.Rf_protect(key) 69 lib.Rf_protect(value) 70 pyo = rcopy(object, obj) 71 try: 72 setattr(pyo, rcopy(key), rcopy(value)) 73 finally: 74 lib.Rf_unprotect(3) 75 return pyo 76 77 def py_set_item(obj, key, value): 78 lib.Rf_protect(obj) 79 lib.Rf_protect(key) 80 lib.Rf_protect(value) 81 pyo = rcopy(object, obj) 82 try: 83 pyo[rcopy(key)] = rcopy(value) 84 finally: 85 lib.Rf_unprotect(3) 86 return pyo 87 88 def py_dict(**kwargs): 89 narg = len(kwargs) 90 for key in kwargs: 91 lib.Rf_protect(kwargs[key]) 92 try: 93 return {key: rcopy(kwargs[key]) for key in kwargs} 94 finally: 95 lib.Rf_unprotect(narg) 96 97 def py_tuple(*args): 98 narg = len(args) 99 for a in args: 100 lib.Rf_protect(a) 101 try: 102 return tuple([rcopy(a) for a in args]) 103 finally: 104 lib.Rf_unprotect(narg) 105 106 def py_unicode(obj): 107 return text_type(obj) 108 109 def assign(name, value, envir): 110 rcall(("base", "assign"), name, value, envir=envir) 111 112 e = rcall(("base", "new.env"), parent=lib.R_GlobalEnv) 113 kwarg = {"rchitect.py_tools": e} 114 rcall(("base", "options"), **kwarg) 115 116 assign("import", rfunction(py_import, convert=False), e) 117 assign("import_builtins", rfunction(py_import_builtins, convert=False), e) 118 assign("py_call", rfunction(py_call, convert=False), e) 119 assign("py_copy", rfunction(py_copy, convert=True), e) 120 assign("py_eval", rfunction(py_eval, convert=False), e) 121 assign("py_get_attr", rfunction(py_get_attr, convert=False), e) 122 assign("py_get_item", rfunction(py_get_item, convert=False), e) 123 assign("py_object", rfunction(py_object, asis=True, convert=False), e) 124 assign("py_set_attr", rfunction(py_set_attr, invisible=True, asis=True, convert=False), e) 125 assign("py_set_item", rfunction(py_set_item, invisible=True, asis=True, convert=False), e) 126 assign("py_unicode", rfunction(py_unicode, convert=False), e) 127 assign("dict", rfunction(py_dict, asis=True, convert=False), e) 128 assign("tuple", rfunction(py_tuple, asis=True, convert=False), e) 129 130 assign("names.PyObject", rfunction(py_names, convert=True), e) 131 assign("print.PyObject", rfunction(py_print, invisible=True, convert=False), e) 132 assign(".DollarNames.PyObject", rfunction(py_names, convert=True), e) 133 assign("$.PyObject", rfunction(py_get_attr, convert=True), e) 134 assign("[.PyObject", rfunction(py_get_item, convert=True), e) 135 assign("$<-.PyObject", rfunction(py_set_attr, invisible=True, asis=True, convert=False), e) 136 assign("[<-.PyObject", rfunction(py_set_item, invisible=True, asis=True, convert=False), e) 137 assign("&.PyObject", rfunction(operator.and_, invisible=True, convert=False), e) 138 assign("|.PyObject", rfunction(operator.or_, invisible=True, convert=False), e) 139 assign("!.PyObject", rfunction(operator.not_, invisible=True, convert=False), e) 140 141 def attach(): 142 parent_frame = rcall("sys.frame", -1) 143 things = [ 144 "import", 145 "import_builtins", 146 "py_call", 147 "py_copy", 148 "py_eval", 149 "py_get_attr", 150 "py_get_item", 151 "py_object", 152 "py_set_attr", 153 "py_set_item", 154 "py_unicode", 155 "dict", 156 "tuple", 157 "names.PyObject", 158 "print.PyObject", 159 ".DollarNames.PyObject", 160 "$.PyObject", 161 "[.PyObject", 162 "$<-.PyObject", 163 "[<-.PyObject", 164 "&.PyObject", 165 "|.PyObject", 166 "!.PyObject" 167 ] 168 for thing in things: 169 assign(thing, get_p(thing, e), parent_frame) 170 171 assign("attach", robject(attach, invisible=True), e) 172