# HG changeset patch # User Stefano Rivera # Date 1378136625 -7200 # Node ID 568476db7115b7fee44c69ca031a25cf5827c6cd # Parent 67f18e72024db358f442da62557c2dc63fac3f70 Dump inline lists and dicts too diff -r 67f18e72024d -r 568476db7115 nagslang/yamlish.py --- 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':