Changes in trunk/lib/syck/loaders.py [18:25]
- File:
-
- 1 edited
-
trunk/lib/syck/loaders.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/syck/loaders.py
r18 r25 1 """ 2 syck.loaders is a high-level wrapper for the Syck YAML parser. 3 Do not use it directly, use the module 'syck' instead. 4 """ 1 5 2 6 # Python 2.2 compatibility … … 21 25 import _syck 22 26 23 import re27 import sys, re 24 28 25 29 __all__ = ['GenericLoader', 'Loader', … … 27 31 28 32 class GenericLoader(_syck.Parser): 33 """ 34 GenericLoader constructs primitive Python objects from YAML documents. 35 """ 29 36 30 37 def load(self): 38 """ 39 Loads a YAML document from the source and return a native Python 40 object. On EOF, returns None and set the eof attribute on. 41 """ 31 42 node = self.parse() 32 43 if self.eof: … … 50 61 value_object = self._convert(node.value[key_node], 51 62 node_to_object) 52 if key_object in value:53 value = None54 break55 63 try: 64 if key_object in value: 65 value = None 66 break 56 67 value[key_object] = value_object 57 68 except TypeError: … … 61 72 value = [] 62 73 for key_node in node.value: 63 key_object = self _convert(key_node, node_to_object)74 key_object = self._convert(key_node, node_to_object) 64 75 value_object = self._convert(node.value[key_node], 65 76 node_to_object) … … 71 82 72 83 def construct(self, node): 84 """Constructs a Python object by the given node.""" 73 85 return node.value 74 86 75 87 class Merge: 88 """Represents the merge key '<<'.""" 76 89 pass 77 90 78 91 class Default: 92 """Represents the default key '='.""" 79 93 pass 80 94 81 95 class Loader(GenericLoader): 96 """ 97 Loader constructs native Python objects from YAML documents. 98 """ 82 99 83 100 inf_value = 1e300000 84 101 nan_value = inf_value/inf_value 85 102 86 ymd_expr = re.compile(r'(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)')87 103 timestamp_expr = re.compile(r'(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)' 88 104 r'(?:' … … 95 111 default_key = Default() 96 112 97 def __init__(self, *args, **kwds): 98 super(Loader, self).__init__(*args, **kwds) 99 self.tags = {} 100 self.add_builtin_types() 101 102 def add_builtin_types(self): 103 self.add_builtin_type('null', lambda node: None) 104 self.add_builtin_type('bool#yes', lambda node: True) 105 self.add_builtin_type('bool#no', lambda node: False) 106 self.add_builtin_type('float#fix', lambda node: float(node.value)) 107 self.add_builtin_type('float#exp', lambda node: float(node.value)) 108 self.add_builtin_type('float#base60', 'construct_base60_float') 109 self.add_builtin_type('float#inf', lambda node: self.inf_value) 110 self.add_builtin_type('float#neginf', lambda node: -self.inf_value) 111 self.add_builtin_type('float#nan', lambda node: self.nan_value) 112 self.add_builtin_type('int', lambda node: int(node.value)) 113 self.add_builtin_type('int#hex', lambda node: int(node.value, 16)) 114 self.add_builtin_type('int#oct', lambda node: int(node.value, 8)) 115 self.add_builtin_type('int#base60', 'construct_base60_int') 116 self.add_builtin_type('binary', lambda node: node.value.decode('base64')) 117 self.add_builtin_type('timestamp#ymd', 'construct_timestamp') 118 self.add_builtin_type('timestamp#iso8601', 'construct_timestamp') 119 self.add_builtin_type('timestamp#spaced', 'construct_timestamp') 120 self.add_builtin_type('timestamp', 'construct_timestamp') 121 self.add_builtin_type('merge', 'construct_merge') 122 self.add_builtin_type('default', 'construct_default') 123 self.add_builtin_type('omap', 'construct_omap') 124 self.add_builtin_type('pairs', 'construct_pairs') 125 self.add_builtin_type('set', 'construct_set') 126 127 def add_type(self, type_tag, constuctor): 128 self.tags[type_tag] = constructor 129 130 def add_domain_type(self, domain, type_tag, constructor): 131 self.tags['tag:%s:%s' % (domain, type_tag)] = constructor 132 133 def add_builtin_type(self, type_tag, constructor): 134 self.tags['tag:yaml.org,2002:'+type_tag] = constructor 135 136 def add_python_type(self, type_tag, constructor): 137 self.tags['tag:python.yaml.org,2002:'+type_tag] = constructor 138 139 def add_private_type(self, type_tag, constructor): 140 self.tags['x-private:'+type_tag] = constructor 113 non_ascii = [] 114 for i in range(256): 115 ch = chr(i) 116 if ch.isalnum(): 117 non_ascii.append(ch) 118 else: 119 non_ascii.append('_') 120 non_ascii = ''.join(non_ascii) 121 122 python_bools = {'True': True, 'False': False} 123 124 class python_class: 125 pass 126 127 def find_constructor(self, node): 128 """ 129 Returns the contructor for generating a Python object for the given 130 node. 131 132 The node tags are mapped to constructors by the following rule: 133 134 Tag Constructor 135 --- ----------- 136 tag:yaml.org,2002:type construct_type 137 tag:python.yaml.org,2002:type construct_python_type 138 x-private:type construct_private_type 139 tag:domain.tld,2002:type construct_domain_tld_2002_type 140 141 See the method code for more details. 142 """ 143 parts = [] 144 if node.tag: 145 parts = node.tag.split(':') 146 if parts: 147 if parts[0] == 'tag': 148 parts.pop(0) 149 if parts: 150 if parts[0] == 'yaml.org,2002': 151 parts.pop(0) 152 elif parts[0] == 'python.yaml.org,2002': 153 parts[0] = 'python' 154 elif parts[0] == 'x-private': 155 parts[0] = 'private' 156 parts = [part.translate(self.non_ascii) for part in parts] 157 while parts: 158 method = 'construct_'+'_'.join(parts) 159 if hasattr(self, method): 160 return getattr(self, method) 161 parts.pop() 141 162 142 163 def construct(self, node): 164 """Constructs a Python object by the given node.""" 143 165 if node.kind == 'map' and self.merge_key in node.value: 144 166 self.merge_maps(node) 145 if node.tag in self.tags: 146 constructor = self.tags[node.tag] 147 if isinstance(constructor, str): 148 constructor = getattr(self, constructor) 167 constructor = self.find_constructor(node) 168 if constructor: 149 169 return constructor(node) 150 170 else: 151 171 return node.value 152 172 153 def construct_base60_float(self, node): 154 return self.construct_base60(float, node) 155 156 def construct_base60_int(self, node): 157 return self.construct_base60(int, node) 158 159 def construct_base60(self, num_type, node): 173 def construct_null(self, node): 174 return None 175 176 def construct_bool_yes(self, node): 177 return True 178 179 def construct_bool_no(self, node): 180 return False 181 182 def construct_numeric_base60(self, num_type, node): 160 183 digits = [num_type(part) for part in node.value.split(':')] 161 184 digits.reverse() … … 166 189 base *= 60 167 190 return value 191 192 def construct_int(self, node): 193 return int(node.value) 194 195 def construct_int_hex(self, node): 196 return int(node.value, 16) 197 198 def construct_int_oct(self, node): 199 return int(node.value, 8) 200 201 def construct_int_base60(self, node): 202 return self.construct_numeric_base60(int, node) 203 204 def construct_float(self, node): 205 return float(node.value) 206 construct_float_fix = construct_float 207 construct_float_exp = construct_float 208 209 def construct_float_base60(self, node): 210 return self.construct_numeric_base60(float, node) 211 212 def construct_float_inf(self, node): 213 return self.inf_value 214 215 def construct_float_neginf(self, node): 216 return -self.inf_value 217 218 def construct_float_nan(self, node): 219 return self.nan_value 220 221 def construct_binary(self, node): 222 return node.value.decode('base64') 168 223 169 224 def construct_timestamp(self, node): … … 183 238 diff = datetime.timedelta(hours=values['zhour'], minutes=values['zminute']) 184 239 return stamp-diff 240 construct_timestamp_ymd = construct_timestamp 241 construct_timestamp_iso8601 = construct_timestamp 242 construct_timestamp_spaced = construct_timestamp 185 243 186 244 def construct_merge(self, node): … … 217 275 return sets.Set(node.value) 218 276 219 def parse(source): 277 def construct_python_none(self, node): 278 return None 279 280 def construct_python_bool(self, node): 281 return self.python_bools[node.value] 282 283 def construct_python_int(self, node): 284 return int(node.value) 285 286 def construct_python_long(self, node): 287 return long(node.value) 288 289 def construct_python_float(self, node): 290 return float(node.value) 291 292 def construct_python_str(self, node): 293 return str(node.value) 294 295 def construct_python_unicode(self, node): 296 return unicode(node.value, 'utf-8') 297 298 def construct_python_list(self, node): 299 return node.value 300 301 def construct_python_tuple(self, node): 302 return tuple(node.value) 303 304 def construct_python_dict(self, node): 305 return node.value 306 307 def find_python_object(self, node): 308 full_name = node.tag.split(':')[3] 309 parts = full_name.split('.') 310 object_name = parts.pop() 311 module_name = '.'.join(parts) 312 if not module_name: 313 module_name = '__builtin__' 314 else: 315 __import__(module_name) 316 return getattr(sys.modules[module_name], object_name) 317 318 def find_python_state(self, node): 319 if node.kind == 'seq': 320 args = node.value 321 kwds = {} 322 state = {} 323 else: 324 args = node.value.get('args', []) 325 kwds = node.value.get('kwds', {}) 326 state = node.value.get('state', {}) 327 return args, kwds, state 328 329 def set_python_state(self, object, state): 330 if hasattr(object, '__setstate__'): 331 object.__setstate__(state) 332 else: 333 slotstate = {} 334 if isinstance(state, tuple) and len(state) == 2: 335 state, slotstate = state 336 if hasattr(object, '__dict__'): 337 object.__dict__.update(state) 338 elif state: 339 slotstate.update(state) 340 for key, value in slotstate.items(): 341 setattr(object, key, value) 342 343 def construct_python_name(self, node): 344 return self.find_python_object(node) 345 346 def construct_python_object(self, node): 347 cls = self.find_python_object(node) 348 if type(cls) is type(self.python_class): 349 if hasattr(cls, '__getnewargs__'): 350 object = cls() 351 else: 352 object = self.python_class() 353 object.__class__ = cls 354 else: 355 object = cls.__new__(cls) 356 self.set_python_state(object, node.value) 357 return object 358 359 def construct_python_new(self, node): 360 cls = self.find_python_object(node) 361 args, kwds, state = self.find_python_state(node) 362 if type(cls) is type(self.python_class): 363 object = cls(*args, **kwds) 364 else: 365 object = cls.__new__(cls, *args, **kwds) 366 self.set_python_state(object, state) 367 return object 368 369 def construct_python_apply(self, node): 370 constructor = self.find_python_object(node) 371 args, kwds, state = self.find_python_state(node) 372 object = constructor(*args, **kwds) 373 self.set_python_state(object, state) 374 return object 375 376 def parse(source, Loader=Loader, **parameters): 220 377 """Parses 'source' and returns the root of the 'Node' graph.""" 221 loader = Loader(source )378 loader = Loader(source, **parameters) 222 379 return loader.parse() 223 380 224 def load(source ):381 def load(source, Loader=Loader, **parameters): 225 382 """Parses 'source' and returns the root object.""" 226 loader = Loader(source )383 loader = Loader(source, **parameters) 227 384 return loader.load() 228 385 229 def parse_documents(source ):230 """Iterates over 'source' and yields the root node ofeach document."""231 loader = Loader(source )386 def parse_documents(source, Loader=Loader, **parameters): 387 """Iterates over 'source' and yields the root 'Node' for each document.""" 388 loader = Loader(source, **parameters) 232 389 while True: 233 390 node = loader.parse() … … 236 393 yield node 237 394 238 def load_documents(source ):239 """Iterates over 'source' and yields the root object ofeach document."""240 loader = Loader(source )395 def load_documents(source, Loader=Loader, **parameters): 396 """Iterates over 'source' and yields the root object for each document.""" 397 loader = Loader(source, **parameters) 241 398 while True: 242 399 object = loader.load()
Note: See TracChangeset
for help on using the changeset viewer.
