Changeset 111:16d9f3a0dc29 for nagslang
- Timestamp:
- Sep 2, 2013, 12:45:18 PM (7 years ago)
- Branch:
- default
- amend_source:
- 8a314fe69efa27db6994429ce49b0090335e05e9
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
nagslang/yamlish.py
r103 r111 9 9 10 10 def dump(data, file_object): 11 file_object.write( '\n'.join(_dump(data, 0)))11 file_object.write(dump_s(data)) 12 12 13 13 14 def _dump(obj, indent): 15 if isinstance(obj, list): 16 for item in obj: 17 yield '%s- %s' % (' ' * indent, 18 '\n'.join(_dump(item, indent + 2)).strip()) 19 elif isinstance(obj, dict): 20 for k, v in obj.iteritems(): 21 if isinstance(v, basestring): 22 yield '%s%s: %s' % (' ' * indent, k, v) 23 else: 24 extra = 0 if isinstance(v, list) else 2 25 yield '%s%s:\n%s' % (' ' * indent, k, 26 '\n'.join(_dump(v, indent + extra))) 27 elif isinstance(obj, basestring): 28 yield '%s%s' % (' ' * indent, obj) 29 30 31 spaces_re = re.compile(r'^(\s*)(.*)') 32 list_re = re.compile(r'^(-\s+)(.*)') 33 dict_re = re.compile(r'^([^-:]+):\s?(.*)') 14 def dump_s(data): 15 return Dumper().dump(data) 34 16 35 17 36 18 def load(file_object): 37 # Stack of (indent level, container object) 38 stack = [(0, {})] 39 indent = lambda: stack[-1][0] 40 obj = lambda: stack[-1][1] 19 yaml = file_object.read() 20 return load_s(yaml) 41 21 42 # When a dict's value is a nested block, remember the key43 parent_key = None44 22 45 for line in file_object:46 spaces, line = spaces_re.match(line).groups()23 def load_s(yaml): 24 return Parser().parse(yaml) 47 25 48 while len(spaces) < indent():49 stack.pop()50 26 51 lm = list_re.match(line) 52 dm = dict_re.match(line) 53 if len(spaces) == indent(): 27 28 class Dumper(object): 29 def dump(self, data): 30 return '\n'.join(self._dump(data)) 31 32 def _dump(self, data, indent=0): 33 for type_ in (list, dict, basestring): 34 if isinstance(data, type_): 35 f = getattr(self, '_dump_%s' % type_.__name__) 36 return f(data, indent) 37 raise NotImplementedError() 38 39 def _dump_list(self, data, indent): 40 output = [] 41 for item in data: 42 dumped = self._dump(item, indent + 2) 43 dumped[0] = '%s- %s' % (' ' * indent, dumped[0][indent + 2:]) 44 output += dumped 45 return output 46 47 def _dump_dict(self, data, indent): 48 output = [] 49 for k, v in data.iteritems(): 50 output.append('%s%s:' % (' ' * indent, k)) 51 if isinstance(v, dict): 52 output += self._dump(v, indent + 2) 53 elif isinstance(v, list): 54 output += self._dump(v, indent) 55 else: 56 value = self._dump(v) 57 assert len(value) == 1 58 output[-1] += ' %s' % value[0] 59 return output 60 61 def _dump_basestring(self, data, indent): 62 return [' ' * indent + data] 63 64 65 class Parser(object): 66 _spaces_re = re.compile(r'^(\s*)(.*)') 67 _list_re = re.compile(r'^(-\s+)(.*)') 68 _dict_re = re.compile(r'^([^-:]+):\s?(.*)') 69 70 def __init__(self): 71 # Stack of (indent level, container object) 72 self._stack = [(0, {})] 73 # When a dict's value is a nested block, remember the key 74 self._parent_key = None 75 76 @property 77 def _indent(self): 78 return self._stack[-1][0] 79 80 @property 81 def _container(self): 82 return self._stack[-1][1] 83 84 @property 85 def _in_list(self): 86 return isinstance(self._container, list) 87 88 @property 89 def _in_dict(self): 90 return isinstance(self._container, dict) 91 92 def _push(self, container, indent=None): 93 in_list = self._in_list 94 assert in_list or self._parent_key 95 96 if indent is None: 97 indent = self._indent 98 self._stack.append((indent, container())) 99 if in_list: 100 self._stack[-2][1].append(self._container) 101 else: 102 self._stack[-2][1][self._parent_key] = self._container 103 self._parent_key = None 104 105 def parse(self, yaml): 106 for line in yaml.splitlines(): 107 spaces, line = self._spaces_re.match(line).groups() 108 109 while len(spaces) < self._indent: 110 self._stack.pop() 111 112 lm = self._list_re.match(line) 113 dm = self._dict_re.match(line) 114 if len(spaces) == self._indent: 115 if lm and self._in_dict: 116 # Starting a list in a dict 117 self._push(list) 118 elif dm and self._in_list: 119 # Left an embedded list 120 self._stack.pop() 121 122 if len(spaces) > self._indent: 123 assert self._parent_key 124 if dm: 125 # Nested dict 126 self._push(dict, len(spaces)) 127 elif lm: 128 # Over-indented list in a dict 129 self._push(list, len(spaces)) 130 131 indent = self._indent 132 while lm and lm.group(2).startswith('- '): 133 # Nested lists 134 prefix, line = lm.groups() 135 indent += len(prefix) 136 self._push(list, indent) 137 lm = self._list_re.match(line) 138 del indent 139 54 140 if lm: 55 assert isinstance(obj(), list) or parent_key 56 if isinstance(obj(), dict) and parent_key: 57 # Starting a list in a dict 58 stack.append((indent(), [])) 59 stack[-2][1][parent_key] = obj() 60 parent_key = None 61 elif dm and isinstance(obj(), list): 62 # Left an embedded list 63 stack.pop() 141 prefix, line = lm.groups() 142 dm = self._dict_re.match(line) 143 if dm: 144 self._push(dict, self._indent + len(prefix)) 145 else: 146 assert self._in_list 147 self._container.append(line) 64 148 65 if len(spaces) > indent():66 assert parent_key67 149 if dm: 68 # Nested dict 69 stack.append((len(spaces), {})) 70 elif lm: 71 # Over-indented list in a dict 72 stack.append((len(spaces), [])) 73 stack[-2][1][parent_key] = obj() 74 parent_key = None 150 key, value = dm.groups() 151 if value: 152 assert self._in_dict 153 self._container[key] = value 154 else: 155 self._parent_key = key 75 156 76 while lm and lm.group(2).startswith('- '): 77 # Nested lists 78 prefix, line = lm.groups() 79 stack.append((indent() + len(prefix), [])) 80 stack[-2][1].append(obj()) 81 lm = list_re.match(line) 82 83 if lm: 84 prefix, line = lm.groups() 85 dm = dict_re.match(line) 86 if dm: 87 stack.append((indent() + len(prefix), {})) 88 stack[-2][1].append(obj()) 89 else: 90 obj().append(line) 91 92 if dm: 93 key, value = dm.groups() 94 if value: 95 obj()[key] = value 96 else: 97 parent_key = key 98 99 return stack[0][1] 157 return self._stack[0][1]
Note: See TracChangeset
for help on using the changeset viewer.