def call(self, space, __args__): with handles.using(space, __args__.arguments_w[0]) as h_self: n = len(__args__.arguments_w) - 1 with lltype.scoped_alloc(rffi.CArray(llapi.HPy), n) as args_h: i = 0 while i < n: args_h[i] = handles.new(space, __args__.arguments_w[i + 1]) i += 1 h_kw = 0 if __args__.keywords: w_kw = space.newdict() for i in range(len(__args__.keywords)): key = __args__.keywords[i] w_value = __args__.keywords_w[i] space.setitem_str(w_kw, key, w_value) h_kw = handles.new(space, w_kw) fptr = llapi.cts.cast('HPyFunc_initproc', self.cfuncptr) state = space.fromcache(State) try: result = fptr(state.ctx, h_self, args_h, n, h_kw) finally: if h_kw: handles.close(space, h_kw) for i in range(n): handles.close(space, args_h[i]) if rffi.cast(lltype.Signed, result) < 0: # If we're here, it means no exception was set raise oefmt(space.w_SystemError, "Function returned an error result without setting an exception") return space.w_None
def HPy_Bytes(space, ctx, h_obj): # XXX: cpyext checks and returns <NULL>. Add a test to HPy and fix here w_obj = handles.deref(space, h_obj) if space.type(w_obj) is space.w_bytes: # XXX write a test for this case return handles.dup(space, h_obj) w_result = invoke_bytes_method(space, w_obj) if w_result is not None: return handles.new(space, w_result) # return PyBytes_FromObject(space, w_obj) # XXX: write a test for this case buffer = space.buffer_w(w_obj, space.BUF_FULL_RO) w_res = space.newbytes(buffer.as_str()) return handles.new(space, w_res)
def _HPy_New(space, ctx, h_type, data): w_type = handles.deref(space, h_type) w_result = _create_instance(space, w_type) data = llapi.cts.cast('void**', data) data[0] = w_result.hpy_data h = handles.new(space, w_result) return h
def HPyModule_Create(space, ctx, hpydef): modname = rffi.constcharp2str(hpydef.c_m_name) w_mod = Module(space, space.newtext(modname)) # # add the functions defined in hpydef.c_legacy_methods if hpydef.c_legacy_methods: if space.config.objspace.hpy_cpyext_API: pymethods = rffi.cast(rffi.VOIDP, hpydef.c_legacy_methods) attach_legacy_methods(space, pymethods, w_mod, modname) else: raise oefmt( space.w_RuntimeError, "Module %s contains legacy methods, but _hpy_universal " "was compiled without cpyext support", modname) # # add the native HPy defines if hpydef.c_defines: p = hpydef.c_defines i = 0 while p[i]: # hpy native methods hpymeth = p[i].c_meth name = rffi.constcharp2str(hpymeth.c_name) sig = rffi.cast(lltype.Signed, hpymeth.c_signature) doc = get_doc(hpymeth.c_doc) w_extfunc = interp_extfunc.W_ExtensionFunction( space, name, sig, doc, hpymeth.c_impl, w_mod) space.setattr(w_mod, space.newtext(w_extfunc.name), w_extfunc) i += 1 return handles.new(space, w_mod)
def call_varargs_kw(self, space, h_self, __args__, skip_args, has_keywords): # this function is more or less the equivalent of # ctx_CallRealFunctionFromTrampoline in cpython-universal n = len(__args__.arguments_w) - skip_args # XXX this looks inefficient: ideally, we would like the equivalent of # alloca(): do we have it in RPython? The alternative is to wrap # arguments_w in a tuple, convert to handle and pass it to a C # function whichs calls alloca() and the forwards everything to the # functpr with lltype.scoped_alloc(rffi.CArray(llapi.HPy), n) as args_h: i = 0 while i < n: args_h[i] = handles.new(space, __args__.arguments_w[i + skip_args]) i += 1 if has_keywords: h_result = self.call_keywords(space, h_self, args_h, n, __args__) else: h_result = self.call_varargs(space, h_self, args_h, n) # XXX this should probably be in a try/finally. We should add a # test to check that we don't leak handles for i in range(n): handles.close(space, args_h[i]) return handles.consume(space, h_result)
def HPy_InPlacePower(space, ctx, h1, h2, h3): # CPython seems to have a weird semantics for InPlacePower: if __ipow__ is # defined, the 3rd argument is always ignored (contrarily to what the # documentation says). If now, it falls back to pow, so the 3rd arg is # handled correctly. Here we try to be bug-to-bug compatible w_o1 = handles.deref(space, h1) w_o2 = handles.deref(space, h2) w_o3 = handles.deref(space, h3) w_ipow = space.lookup(w_o1, '__ipow__') if w_ipow is None: w_res = space.pow(w_o1, w_o2, w_o3) else: w_res = space.inplace_pow(w_o1, w_o2) return handles.new(space, w_res)
def HPyUnicode_FromWideChar(space, ctx, wchar_p, size): # remove the "const", else we can't call wcharpsize2utf8 later wchar_p = rffi.cast(rffi.CWCHARP, wchar_p) if wchar_p: if size == -1: size = wcharplen(wchar_p) # WRITE TEST: this automatically raises "character not in range", but # we don't have any test for it s = wcharpsize2utf8(space, wchar_p, size) w_obj = space.newutf8(s, size) return handles.new(space, w_obj) else: # cpyext returns an empty string, we need a test raise NotImplementedError("WRITE TEST")
def call_keywords(self, space, h_self, args_h, n, __args__): state = space.fromcache(State) # XXX: if there are no keywords, should we pass HPy_NULL or an empty # dict? h_kw = 0 if __args__.keywords: w_kw = space.newdict() for i in range(len(__args__.keywords)): key = __args__.keywords[i] w_value = __args__.keywords_w[i] space.setitem_str(w_kw, key, w_value) h_kw = handles.new(space, w_kw) fptr = llapi.cts.cast('HPyFunc_keywords', self.cfuncptr) try: return fptr(state.ctx, h_self, args_h, n, h_kw) finally: if h_kw: handles.consume(space, h_kw)
def HPyType_FromSpec(space, ctx, spec, params): dict_w = {} specname = rffi.constcharp2str(spec.c_name) dotpos = specname.rfind('.') if dotpos < 0: name = specname modname = None else: name = specname[dotpos + 1:] modname = specname[:dotpos] if modname is not None: dict_w['__module__'] = space.newtext(modname) bases_w = get_bases_from_params(space, ctx, params) basicsize = rffi.cast(lltype.Signed, spec.c_basicsize) w_result = _create_new_type(space, space.w_type, name, bases_w, dict_w, basicsize) if spec.c_legacy_slots: attach_legacy_slots_to_type(space, w_result, spec.c_legacy_slots) if spec.c_defines: add_slot_defs(space, ctx, w_result, spec.c_defines) return handles.new(space, w_result)
def HPy_GetAttr(space, ctx, h_obj, h_name): w_obj = handles.deref(space, h_obj) w_name = handles.deref(space, h_name) w_res = space.getattr(w_obj, w_name) return handles.new(space, w_res)
def HPy_RichCompare(space, ctx, v, w, op): w_o1 = handles.deref(space, v) w_o2 = handles.deref(space, w) w_result = rich_compare(space, w_o1, w_o2, op) return handles.new(space, w_result)
def HPy_ASCII(space, ctx, h_obj): w_obj = handles.deref(space, h_obj) w_res = operation.ascii(space, w_obj) return handles.new(space, w_res)
def HPyLong_FromSsize_t(space, ctx, v): # XXX: cpyext uses space.newlong: is there any difference? w_obj = space.newlong_from_rarith_int(v) return handles.new(space, w_obj)
def HPyLong_FromSize_t(space, ctx, v): w_obj = space.newlong_from_rarith_int(v) return handles.new(space, w_obj)
def HPyTupleBuilder_New(space, ctx, initial_size): w_builder = W_TupleBuilder(initial_size) h = handles.new(space, w_builder) return h
def HPyUnicode_FromString(space, ctx, utf8): w_obj = _maybe_utf8_to_w(space, utf8) return handles.new(space, w_obj)
def HPy_GetItem_i(space, ctx, h_obj, idx): w_obj = handles.deref(space, h_obj) w_key = space.newint(idx) w_res = space.getitem(w_obj, w_key) return handles.new(space, w_res)
def HPy_Float(space, ctx, h1): w_obj1 = handles.deref(space, h1) w_res = space.call_function(space.w_float, w_obj1) return handles.new(space, w_res)
def HPyUnicode_AsUTF8String(space, ctx, h): w_unicode = handles.deref(space, h) # XXX: what should we do if w_unicode is not a str? w_bytes = unicodeobject.encode_object(space, w_unicode, 'utf-8', 'strict') return handles.new(space, w_bytes)
def HPy_binary(space, ctx, h1, h2): w_obj1 = handles.deref(space, h1) w_obj2 = handles.deref(space, h2) meth = getattr(space, spacemeth) w_res = meth(w_obj1, w_obj2) return handles.new(space, w_res)
def HPy_unary(space, ctx, h1): w_obj1 = handles.deref(space, h1) meth = getattr(space, spacemeth) w_res = meth(w_obj1) return handles.new(space, w_res)
def HPyTupleBuilder_Build(space, ctx, builder): w_builder = handles.deref(space, builder) assert isinstance(w_builder, W_TupleBuilder) w_tuple = space.newtuple(w_builder.items_w) return handles.new(space, w_tuple)
def HPy_GetAttr_s(space, ctx, h_obj, name): w_obj = handles.deref(space, h_obj) w_name = API.ccharp2text(space, name) w_res = space.getattr(w_obj, w_name) return handles.new(space, w_res)
def HPyTracker_New(space, ctx, size): w_tracker = W_Tracker(size) return handles.new(space, w_tracker)
def HPy_GetItem(space, ctx, h_obj, h_key): w_obj = handles.deref(space, h_obj) w_key = handles.deref(space, h_key) w_res = space.getitem(w_obj, w_key) return handles.new(space, w_res)
def HPyLong_FromLong(space, ctx, value): # XXX: cpyext does space.newlong: write a test and fix w_obj = space.newint(rffi.cast(lltype.Signed, value)) return handles.new(space, w_obj)
def HPy_GetItem_s(space, ctx, h_obj, key): w_obj = handles.deref(space, h_obj) w_key = API.ccharp2text(space, key) w_res = space.getitem(w_obj, w_key) return handles.new(space, w_res)
def HPy_Str(space, ctx, h_obj): # XXX: cpyext checks and returns <NULL>. Add a test to HPy and fix here w_obj = handles.deref(space, h_obj) w_res = space.str(w_obj) return handles.new(space, w_res)
def HPy_Power(space, ctx, h1, h2, h3): w_o1 = handles.deref(space, h1) w_o2 = handles.deref(space, h2) w_o3 = handles.deref(space, h3) w_res = space.pow(w_o1, w_o2, w_o3) return handles.new(space, w_res)
def HPyListBuilder_Build(space, ctx, builder): w_builder = handles.deref(space, builder) assert isinstance(w_builder, W_ListBuilder) w_list = space.newlist(w_builder.items_w) return handles.new(space, w_list)