After taking another look at my patch, I realized that I was not quite
converting dictionaries to proper alists.

Attached is a tweak to do this properly. The printing of dictionaries is
not quite as pretty, in particular it's not a table anymore:

#+begin_src python
  return {"a": 1, "b": 2}

: ((a . 1) (b . 2))

But, it feels like the right thing to do, since the result handling code
works by converting the result to an elisp value, before passing it to
org-mode to decide how to render it. And the proper elisp conversion of
a dict should be an alist or a plist.

Ideally I wouldn't have to do this from the Python code, and could let
org-babel-script-escape convert the dict objects. It would also be
useful for other languages with similar dictionaries, like
javascript. But it seems fairly complex to implement this from the elisp
side, and I'm not sure I'm up for it.

I also noticed that I had left a couple docstrings as TODOs -- I'll fix
those before finalizing the patch over the next couple weeks.

>From 76a1ad4d50e6638244d9aa17e45895b8b38b3cd0 Mon Sep 17 00:00:00 2001
From: Jack Kamm <>
Date: Sun, 30 Aug 2020 08:51:04 -0700
Subject: [PATCH 2/2] Convert dictionary output to a proper alist

Note: to be squashed with the previous patch before merging
 lisp/ob-python.el | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index fb8fe380e..08c1c48e9 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -239,9 +239,14 @@ (defconst org-babel-python--def-format-value "\
             if not set(result_params).intersection(\
 ['scalar', 'verbatim', 'raw']):
+                class alist(dict):
+                    def __str__(self):
+                        return '({})'.format(' '.join(['({} . {})'.format(repr(k), repr(v)) for k, v in self.items()]))
+                    def __repr__(self):
+                        return self.__str__()
                 def dict2alist(res):
                     if isinstance(res, dict):
-                        return [(k, dict2alist(v)) for k, v in res.items()]
+                        return alist({k: dict2alist(v) for k, v in res.items()})
                     elif isinstance(res, list) or isinstance(res, tuple):
                         return [dict2alist(x) for x in res]

Reply via email to