changeset 131:568476db7115

Dump inline lists and dicts too
author Stefano Rivera <stefano@rivera.za.net>
date Mon, 02 Sep 2013 17:43:45 +0200
parents 67f18e72024d
children e1ef3727b7f8
files nagslang/yamlish.py
diffstat 1 files changed, 60 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/nagslang/yamlish.py	Mon Sep 02 17:03:25 2013 +0200
+++ b/nagslang/yamlish.py	Mon Sep 02 17:43:45 2013 +0200
@@ -6,6 +6,7 @@
  * single line strings,
  * ints, floats,
  * True, False, and None
+dict keys can only be strings.
 '''
 
 import re
@@ -30,61 +31,88 @@
 
 class Dumper(object):
     def dump(self, data):
-        return '\n'.join(self._dump(data))
+        return '\n'.join(self._dump_block(data))
 
-    def _dump(self, data, indent=0):
+    def _dump_block(self, data, indent=0):
+        for type_ in (list, dict):
+            if isinstance(data, type_):
+                f = getattr(self, '_dump_%s_block' % type_.__name__)
+                return f(data, indent)
+        raise NotImplementedError()
+
+    def _dump_inline(self, data):
+        if data in (True, False, None):
+            return self._dump_literal(data)
         for type_ in (list, dict, basestring, int, float):
             if isinstance(data, type_):
                 f = getattr(self, '_dump_%s' % type_.__name__)
-                return f(data, indent)
-        if data in (True, False, None):
-            return self._dump_literal(data, indent)
+                return f(data)
         raise NotImplementedError()
 
-    def _dump_list(self, data, indent):
+    def _dump_list_block(self, data, indent):
         output = []
         for item in data:
-            dumped = self._dump(item, indent + 2)
-            dumped[0] = '%s- %s' % (' ' * indent, dumped[0][indent + 2:])
-            output += dumped
+            if self._inlineable(item):
+                output.append('%s- %s' % (' ' * indent,
+                                          self._dump_inline(item)))
+            else:
+                dumped = self._dump_block(item, indent + 2)
+                dumped[0] = '%s- %s' % (' ' * indent, dumped[0][indent + 2:])
+                output += dumped
         return output
 
-    def _dump_dict(self, data, indent):
+    def _dump_dict_block(self, data, indent):
         output = []
         for k, v in sorted(data.iteritems()):
             output.append('%s%s:' % (' ' * indent, k))
-            if isinstance(v, dict):
-                output += self._dump(v, indent + 2)
+            if self._inlineable(v):
+                output[-1] += ' ' + self._dump_inline(v)
+            elif isinstance(v, dict):
+                output += self._dump_block(v, indent + 2)
             elif isinstance(v, list):
-                output += self._dump(v, indent)
+                output += self._dump_block(v, indent)
             else:
-                value = self._dump(v)
-                assert len(value) == 1
-                output[-1] += ' %s' % value[0]
+                raise NotImplementedError()
         return output
 
-    def _dump_basestring(self, data, indent):
-        if data in ('true', 'false', 'null'):
-            data = "'%s'" % data
-        elif "'" in data:
-            data = "'%s'" % data.replace("'", "''")
-        elif data == '':
-            data = "''"
-        return [' ' * indent + data]
+    def _inlineable(self, data):
+        if isinstance(data, list):
+            return all(not isinstance(item, (list, dict)) for item in data)
+        elif isinstance(data, dict):
+            return all(not isinstance(item, (list, dict))
+                       for item in data.itervalues())
+        else:
+            return True
+
+    def _dump_list(self, data):
+        return '[%s]' % ', '.join(self._dump_inline(item) for item in data)
+
+    def _dump_dict(self, data):
+        return '{%s}' % ', '.join(
+                '%s: %s' % (self._dump_inline(key), self._dump_inline(value))
+                for key, value in data.iteritems())
 
-    def _dump_int(self, data, indent):
-        return ['%s%i' % (' ' * indent, data)]
+    def _dump_basestring(self, data):
+        if data in ('true', 'false', 'null'):
+            return "'%s'" % data
+        if "'" in data:
+            return "'%s'" % data.replace("'", "''")
+        if data == '':
+            return "''"
+        return data
 
-    def _dump_float(self, data, indent):
-        return ['%s%f' % (' ' * indent, data)]
+    def _dump_int(self, data):
+        return str(data)
 
-    def _dump_literal(self, data, indent):
-        string = {
+    def _dump_float(self, data):
+        return str(data)
+
+    def _dump_literal(self, data):
+        return {
             True: 'true',
             False: 'false',
             None: 'null',
         }[data]
-        return [' ' * indent + string]
 
 
 class Parser(object):
@@ -213,7 +241,7 @@
                 value = m.group(2)
             return output
         if value.startswith('!!'):
-            raise NotImplemented()
+            raise NotImplementedError()
         if value == 'true':
             return True
         if value == 'false':