def _generate_signal_callback(backend, info, args, arg_types): sig_args = [] ret_type = info.get_return_type() cls = get_cbreturn_class(ret_type) return_value = cls(backend, info, ret_type) for arg, type_ in zip(args, arg_types): cls = get_cbarg_class(type_) excaped_name = escape_identifier(arg.name) sig_arg = cls(backend, arg, type_, excaped_name) sig_args.append(sig_arg) for arg in sig_args: arg.setup() body = CodeBlock() outs_vars = [] for arg in sig_args: if arg.is_aux: continue block, out = arg.process() if block: block.write_into(body) outs_vars.append(out) argument_list = ", ".join([a.name for a in sig_args]) forward_arguments = ", ".join(outs_vars) func_name = escape_parameter(info.name) cb_name = backend.var() return_var = backend.var() return_block, out_var = return_value.process(return_var) return_block = return_block or CodeBlock() block, var = backend.parse(""" def $cb_wrapper($dummy, $args): $body $ret = $callback($out_args) $post return $out """, args=argument_list, out_args=forward_arguments, cb_wrapper=func_name, callback=cb_name, body=body, post=return_block, out=out_var, ret=return_var) def create_sig_for_func(real_func): f = block.compile(**{cb_name: real_func})[func_name] return backend.get_callback(f, sig_args, return_value, is_signal=True) return create_sig_for_func
def generate_callback_wrapper(info): backend = get_backend("ctypes")() args = list(info.get_args()) arg_types = [a.get_type() for a in args] ret_type = info.get_return_type() cls = get_cbreturn_class(ret_type) return_value = cls(backend, info, ret_type) cb_args = [] for arg, type_ in zip(args, arg_types): cls = get_cbarg_class(type_) excaped_name = escape_identifier(arg.name) cb_arg = cls(backend, arg, type_, excaped_name) cb_args.append(cb_arg) for arg in cb_args: arg.setup() body = CodeBlock() outs_vars = [] for arg in cb_args: if arg.is_aux: continue block, out = arg.process() if block: block.write_into(body) outs_vars.append(out) arg_names = [a.name for a in cb_args] backend.var.add_blacklist(arg_names) argument_list = ", ".join(arg_names) forward_arguments = ", ".join(outs_vars) func_name = escape_parameter(info.name) cb_name = backend.var() return_var = backend.var() return_block, out_var = return_value.process(return_var) return_block = return_block or CodeBlock() docstring = build_docstring(func_name, cb_args) block, var = backend.parse(""" def $cb_wrapper($args): $body # $docstring $ret = $callback($out_args) $post return $out """, args=argument_list, out_args=forward_arguments, cb_wrapper=func_name, callback=cb_name, body=body, docstring=docstring, ret=return_var, out=out_var, post=return_block) def create_cb_for_func(real_func): if real_func is not None: # binds the callback to the block and compiles it func = block.compile(**{cb_name: real_func})[func_name] else: func = None return backend.get_callback(func, cb_args, return_value) return create_cb_for_func, docstring
def generate_dummy_callable(info, func_name, method=False, signal_owner_type=None): """Takes a GICallableInfo and generates a dummy callback function which just raises but has a correct docstring. They are mainly accessible for documentation, so the API reference can reference a real thing. func_name can be different than info.name because vfuncs, for example, get prefixed with 'do_' when exposed in Python. """ assert isinstance(info, GICallableInfo) # FIXME: handle out args and trailing user_data ? arg_infos = list(info.get_args()) arg_types = [a.get_type() for a in arg_infos] return_type = info.get_return_type() # the null backend is good enough here backend = get_backend("null")() args = [] for arg_info, arg_type in zip(arg_infos, arg_types): cls = get_argument_class(arg_type) name = escape_identifier(arg_info.name) name = escape_parameter(name) args.append(cls(name, args, backend, arg_info, arg_type)) cls = get_return_class(return_type) return_value = cls(info, return_type, args, backend) for arg in args: arg.setup() return_value.setup() func_name = escape_identifier(func_name) docstring = build_docstring(func_name, args, return_value, False, signal_owner_type) in_args = [a for a in args if not a.is_aux and a.in_var] in_names = [a.in_var for a in in_args] var_fac = backend.var var_fac.add_blacklist(in_names) self_name = "" if method: self_name = var_fac.request_name("self") in_names.insert(0, self_name) main, var = backend.parse(""" def $func_name($func_args): '''$docstring''' raise NotImplementedError("This is just a dummy callback function") """, func_args=", ".join(in_names), docstring=docstring, func_name=func_name) func = main.compile()[func_name] func._code = main func.__doc__ = docstring func.__module__ = info.namespace return func
def test_escape_property(self): self.assertEqual(escape_parameter("class"), "class_") self.assertEqual(escape_parameter("cla-ss"), "cla_ss") self.assertEqual(escape_parameter("2BUTTON_PRESS"), "_2BUTTON_PRESS")
def generate_dummy_callable(info, func_name, method=False): """Takes a GICallableInfo and generates a dummy callback function which just raises but has a correct docstring. They are mainly accessible for documentation, so the API reference can reference a real thing. func_name can be different than info.name because vfuncs, for example, get prefixed with 'do_' when exposed in Python. """ assert isinstance(info, GICallableInfo) # FIXME: handle out args and trailing user_data ? arg_infos = list(info.get_args()) arg_types = [a.get_type() for a in arg_infos] return_type = info.get_return_type() # the null backend is good enough here backend = get_backend("null")() args = [] for arg_info, arg_type in zip(arg_infos, arg_types): cls = get_argument_class(arg_type) name = escape_identifier(arg_info.name) name = escape_parameter(name) args.append(cls(name, args, backend, arg_info, arg_type)) cls = get_return_class(return_type) return_value = cls(info, return_type, args, backend) for arg in args: arg.setup() return_value.setup() func_name = escape_identifier(func_name) docstring = build_docstring(func_name, args, return_value, False) in_args = [a for a in args if not a.is_aux and a.in_var] in_names = [a.in_var for a in in_args] var_fac = backend.var var_fac.add_blacklist(in_names) self_name = "" if method: self_name = var_fac.request_name("self") in_names.insert(0, self_name) main, var = backend.parse(""" def $func_name($func_args): '''$docstring''' raise NotImplementedError("This is just a dummy callback function") """, func_args=", ".join(in_names), docstring=docstring, func_name=func_name) func = main.compile()[func_name] func._code = main func.__doc__ = docstring func.__module__ = info.namespace return func