|
@@ -226,7 +226,7 @@ cdef class EmacsValue:
|
|
|
return self.as_list()
|
|
|
elif my_type == "hash-table":
|
|
|
return self.as_dict()
|
|
|
- raise ValueError("Unable to export emacs value")
|
|
|
+ raise ValueError(f"Unable to export emacs value of type '{my_type} ({str(self)})'")
|
|
|
|
|
|
def __str__(self):
|
|
|
return _F().prin1_to_string(self).str()
|
|
@@ -246,6 +246,8 @@ cdef emacs_value unwrap(obj) except *:
|
|
|
obj = make_list(obj)
|
|
|
elif isinstance(obj, tuple):
|
|
|
obj = make_list(list(obj))
|
|
|
+ elif isinstance(obj, dict):
|
|
|
+ obj = make_dict(obj)
|
|
|
|
|
|
if isinstance(obj, EmacsValue):
|
|
|
return (<EmacsValue>obj).v
|
|
@@ -282,6 +284,16 @@ cpdef make_bool(bool b):
|
|
|
cpdef make_list(list l):
|
|
|
return funcall(sym("list"), l)
|
|
|
|
|
|
+cpdef make_dict(dict d):
|
|
|
+ if not d:
|
|
|
+ return funcall(sym("make-hash-table"), [])
|
|
|
+ keys = []
|
|
|
+ values = []
|
|
|
+ for k, v in d.items():
|
|
|
+ keys.append(k)
|
|
|
+ values.append(v)
|
|
|
+ return funcall(sym("emacspy--lists-to-hash-table"), [keys, values])
|
|
|
+
|
|
|
cdef emacs_value string_ptr(str s):
|
|
|
cdef emacs_env* env = get_env()
|
|
|
s_utf8 = s.encode('utf8')
|
|
@@ -342,7 +354,7 @@ cdef emacs_value call_python_object(emacs_env *env, ptrdiff_t nargs, emacs_value
|
|
|
c_result = unwrap(result)
|
|
|
except BaseException as exc:
|
|
|
c_result = string_ptr("error")
|
|
|
- msg = type(exc).__name__ + ': ' + str(exc)
|
|
|
+ msg = type(exc).__name__ + ': ' + str(exc) + "\n" + traceback.format_exc()
|
|
|
env.non_local_exit_signal(env, sym_ptr('python-exception'), string_ptr(msg))
|
|
|
|
|
|
current_env = prev_env
|
|
@@ -365,8 +377,7 @@ cdef extern from "subinterpreter.c":
|
|
|
object destroy_subinterpreter(char*)
|
|
|
object list_subinterpreters()
|
|
|
object run_string(char*, char*, object)
|
|
|
- object call_method(char*, object, object, object, object, object)
|
|
|
- object call_function(char*, object, object, object)
|
|
|
+ object call_py(char*, object, object, object, object, object)
|
|
|
object import_module(char*, object, object)
|
|
|
object get_global_variable(char*, object)
|
|
|
object get_object_attr(char*, object, object, object)
|
|
@@ -424,33 +435,18 @@ def init():
|
|
|
raise ret
|
|
|
return ret
|
|
|
|
|
|
- @defun('py-call-method')
|
|
|
- def call_object_python(interpreter_name, obj_name, method_name, target_name='', *args):
|
|
|
- if target_name and target_name.to_python_type():
|
|
|
- target_name = target_name.to_python_type()
|
|
|
- else:
|
|
|
- target_name = ''
|
|
|
- args_py = list((arg.to_python_type() for arg in args))
|
|
|
- ret = call_method(str_elisp2c(interpreter_name), obj_name.to_python_type(), \
|
|
|
- method_name.to_python_type(), tuple(), target_name, args_py)
|
|
|
- if isinstance(ret, BaseException):
|
|
|
- raise ret
|
|
|
- return ret
|
|
|
-
|
|
|
- @defun('py-call-function')
|
|
|
- def call_function_python(interpreter_name, function_name, target_name='', *args):
|
|
|
- if target_name and target_name.to_python_type():
|
|
|
- target_name = target_name.to_python_type()
|
|
|
- else:
|
|
|
- target_name = ''
|
|
|
- args_py = tuple((arg.to_python_type() for arg in args))
|
|
|
- ret = call_function(str_elisp2c(interpreter_name), function_name.to_python_type(), \
|
|
|
- target_name, args_py)
|
|
|
+ @defun('emacspy--call')
|
|
|
+ def call_function_python(interpreter_name, object_name, method_name, target_name, args, kwargs):
|
|
|
+ target_name_py: str = target_name.to_python_type() or ''
|
|
|
+ args_py: tuple = tuple(args.to_python_type() or tuple())
|
|
|
+ kwargs_py: dict = kwargs.to_python_type() or {}
|
|
|
+ ret = call_py(str_elisp2c(interpreter_name), \
|
|
|
+ object_name.to_python_type(), method_name.to_python_type(), \
|
|
|
+ target_name_py, args_py, kwargs_py)
|
|
|
if isinstance(ret, BaseException):
|
|
|
raise ret
|
|
|
return ret
|
|
|
|
|
|
-
|
|
|
@defun('py-get-global-variable')
|
|
|
def get_global_var(interpreter_name, var_name):
|
|
|
ret = get_global_variable(str_elisp2c(interpreter_name), var_name.to_python_type())
|