- Location:
- /trunk
- Files:
-
- 6 added
- 13 edited
-
lib/syck/loaders.py (modified) (11 diffs)
-
lib/syck/__init__.py (modified) (1 diff)
-
lib/syck/dumpers.py (modified) (10 diffs)
-
setup.py (modified) (3 diffs)
-
MANIFEST.in (added)
-
README.txt (added)
-
Makefile (modified) (2 diffs)
-
sandbox/emit-it/complex-key-bug.c (added)
-
sandbox/emit-it/emit-it.c (modified) (4 diffs)
-
sandbox/emit-it/Makefile (modified) (1 diff)
-
sandbox/emit-it/trailing-space-bug.c (added)
-
sandbox/syck-parser/test_my_tags.yml (added)
-
ext/_syckmodule.c (modified) (15 diffs)
-
tests/test_loader.py (modified) (5 diffs)
-
tests/test_pickle.py (added)
-
tests/test_emitter.py (modified) (3 diffs)
-
tests/test_syck.py (modified) (1 diff)
-
tests/test_dumper.py (modified) (2 diffs)
-
tests/test_parser.py (modified) (1 diff)
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() -
/trunk/lib/syck/__init__.py
r19 r25 1 """ 2 YAML is a data serialization format designed for human readability and 3 interaction with scripting languages. 4 5 Syck is an extension for reading and writing YAML in scripting languages. 6 7 PySyck provides Python bindings for Syck YAML parser and emitter. 8 9 To start working with PySyck, import the package 'syck': 10 >>> from syck import * 11 12 To parse a YAML document into a Python object, use the function 'load()': 13 >>> load(''' 14 ... - Mark McGwire 15 ... - Sammy Sosa 16 ... - Ken Griffey 17 ... ''') 18 ['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'] 19 20 To emit a Python object into a YAML document, use the function 'dump()': 21 >>> print dump(['Mark McGwire', 'Sammy Sosa', 'Ken Griffey']) 22 --- 23 - Mark McGwire 24 - Sammy Sosa 25 - Ken Griffey 26 27 You may get access to the YAML parser tree using the function 'parse()': 28 >>> root_node = parse(''' 29 ... - Mark McGwire 30 ... - Sammy Sosa 31 ... - Ken Griffey 32 ... ''') 33 >>> root_node 34 <_syck.Seq object at 0xb7a1f874> 35 >>> root_node.kind 36 'seq' 37 >>> root_node.value 38 [<_syck.Scalar object at 0xb7a1e5fc>, <_syck.Scalar object at 0xb7a1e65c>, <_syck.Scalar object at 0xb7a1e6bc>] 39 40 You may now use the function 'emit()' to obtain the YAML document again: 41 >>> print emit(root_node) 42 --- 43 - Mark McGwire 44 - Sammy Sosa 45 - Ken Griffey 46 47 What do you get if you apply the function 'dump()' to root_node? Let's try it: 48 >>> print dump(root_node) 49 --- !python/object:_syck.Seq 50 value: 51 - !python/object:_syck.Scalar 52 value: Mark McGwire 53 tag: tag:yaml.org,2002:str 54 - !python/object:_syck.Scalar 55 value: Sammy Sosa 56 tag: tag:yaml.org,2002:str 57 - !python/object:_syck.Scalar 58 value: Ken Griffey 59 tag: tag:yaml.org,2002:str 60 61 As you can see, PySyck allow you to represent complex Python objects. 62 63 You can also dump the generated YAML output into any file-like object: 64 >>> import os 65 >>> stream = os.tmpfile() 66 >>> object = ['foo', 'bar', ['baz']] 67 >>> dump(object, stream) 68 >>> stream.seek(0) 69 >>> print stream.read() 70 --- 71 - foo 72 - bar 73 - - baz 74 75 To load several documents from a single YAML stream, use the function 76 'load_documents()': 77 >>> source = ''' 78 ... --- 79 ... american: 80 ... - Boston Red Sox 81 ... - Detroit Tigers 82 ... - New York Yankees 83 ... national: 84 ... - New York Mets 85 ... - Chicago Cubs 86 ... - Atlanta Braves 87 ... --- 88 ... - [name , hr, avg ] 89 ... - [Mark McGwire, 65, 0.278] 90 ... - [Sammy Sosa , 63, 0.288] 91 ... ''' 92 >>> for document in load_documents(source): 93 ... print document 94 ... 95 {'national': ['New York Mets', 'Chicago Cubs', 'Atlanta Braves'], 'american': ['Boston Red Sox', 'Detroit Tigers', 'New York Yankees']} 96 [['name', 'hr', 'avg'], ['Mark McGwire', 65, 0.27800000000000002], ['Sammy Sosa', 63, 0.28799999999999998]] 97 98 See the source code for more details. 99 """ 100 1 101 2 102 from _syck import * -
/trunk/lib/syck/dumpers.py
r20 r25 1 """ 2 syck.dumpers is a high-level wrapper for the Syck YAML emitter. 3 Do not use it directly, use the module 'syck' instead. 4 """ 1 5 2 6 import _syck … … 10 14 'emit', 'dump', 'emit_documents', 'dump_documents'] 11 15 12 INF = 1e30000013 NEGINF = -INF14 NAN = INF/INF15 16 17 16 class GenericDumper(_syck.Emitter): 17 """ 18 GenericDumper dumps native Python objects into YAML documents. 19 """ 18 20 19 21 def dump(self, object): 22 """Dumps the given Python object as a YAML document.""" 20 23 self.emit(self._convert(object, {})) 21 24 22 25 def _convert(self, object, object_to_node): 23 26 if id(object) in object_to_node and self.allow_aliases(object): 24 return object_to_node[id(object)] 27 return object_to_node[id(object)][1] 25 28 node = self.represent(object) 26 object_to_node[id(object)] = node29 object_to_node[id(object)] = object, node 27 30 if node.kind == 'seq': 28 for index, item in enumerate(node.value): 31 for index in range(len(node.value)): 32 item = node.value[index] 29 33 node.value[index] = self._convert(item, object_to_node) 30 34 elif node.kind == 'map': 31 for key in node.value.keys(): 32 value = node.value[key] 33 del node.value[key] 34 node.value[self._convert(key, object_to_node)] = \ 35 self._convert(value, object_to_node) 35 if isinstance(node.value, dict): 36 for key in node.value.keys(): 37 value = node.value[key] 38 del node.value[key] 39 node.value[self._convert(key, object_to_node)] = \ 40 self._convert(value, object_to_node) 41 elif isinstance(node.value, list): 42 for index in range(len(node.value)): 43 key, value = node.value[index] 44 node.value[index] = (self._convert(key, object_to_node), 45 self._convert(value, object_to_node)) 36 46 # # Workaround against a Syck bug: 37 47 # if node.kind == 'scalar' and node.style not in ['1quote', '2quote'] \ … … 41 51 42 52 def represent(self, object): 53 """Represents the given Python object as a 'Node'.""" 43 54 if isinstance(object, dict): 44 55 return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map") … … 49 60 50 61 def allow_aliases(self, object): 62 """Checks whether the given object can be aliased.""" 51 63 return True 52 64 53 65 class Dumper(GenericDumper): 54 55 def __init__(self, *args, **kwds): 56 super(Dumper, self).__init__(*args, **kwds) 57 58 def represent(self, object): 66 """ 67 Dumper dumps native Python objects into YAML documents. 68 """ 69 70 INF = 1e300000 71 inf_value = repr(INF) 72 neginf_value = repr(-INF) 73 nan_value = repr(INF/INF) 74 75 def find_representer(self, object): 76 """ 77 For the given object, find a method that can represent it as a 'Node' 78 object. 79 80 If the type of the object has the form 'package.module.type', 81 find_representer() returns the method 'represent_package_module_type'. 82 If this method does not exist, it checks the base types. 83 """ 59 84 for object_type in type(object).__mro__: 60 85 if object_type.__module__ == '__builtin__': … … 62 87 else: 63 88 name = '%s.%s' % (object_type.__module__, object_type.__name__) 64 method = 'represent_ %s' %name.replace('.', '_')89 method = 'represent_' + name.replace('.', '_') 65 90 if hasattr(self, method): 66 return getattr(self, method)(object) 67 return super(Dumper, self).represent(object) 91 return getattr(self, method) 92 93 def represent(self, object): 94 """Represents the given Python object as a 'Node'.""" 95 representer = self.find_representer(object) 96 if representer: 97 return representer(object) 98 else: 99 return super(Dumper, self).represent(object) 68 100 69 101 def represent_object(self, object): … … 88 120 return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int") 89 121 90 def represent_int(self, object):91 return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int")92 93 122 def represent_float(self, object): 94 123 value = repr(object) 95 if value == repr(INF):124 if value == self.inf_value: 96 125 value = '.inf' 97 elif value == repr(NEGINF):126 elif value == self.neginf_value: 98 127 value = '-.inf' 99 elif value == repr(NAN):128 elif value == self.nan_value: 100 129 value = '.nan' 101 130 return _syck.Scalar(value, tag="tag:yaml.org,2002:float") … … 103 132 def represent_sets_Set(self, object): 104 133 return _syck.Seq(list(object), tag="tag:yaml.org,2002:set") 134 represent_set = represent_sets_Set 105 135 106 136 def represent_datetime_datetime(self, object): 107 137 return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp") 108 138 139 def represent_long(self, object): 140 return _syck.Scalar(repr(object), tag="tag:python.yaml.org,2002:long") 141 142 def represent_unicode(self, object): 143 return _syck.Scalar(object.encode('utf-8'), tag="tag:python.yaml.org,2002:unicode") 144 145 def represent_tuple(self, object): 146 return _syck.Seq(list(object), tag="tag:python.yaml.org,2002:tuple") 147 148 def represent_type(self, object): 149 name = '%s.%s' % (object.__module__, object.__name__) 150 return _syck.Scalar('', tag="tag:python.yaml.org,2002:name:"+name) 151 represent_classobj = represent_type 152 represent_class = represent_type 153 # TODO: Python 2.2 does not provide the module name of a function 154 represent_function = represent_type 155 represent_builtin_function_or_method = represent_type 156 157 def represent_instance(self, object): 158 cls = object.__class__ 159 class_name = '%s.%s' % (cls.__module__, cls.__name__) 160 args = () 161 state = {} 162 if hasattr(object, '__getinitargs__'): 163 args = object.__getinitargs__() 164 if hasattr(object, '__getstate__'): 165 state = object.__getstate__() 166 elif not hasattr(object, '__getinitargs__'): 167 state = object.__dict__.copy() 168 if not args and isinstance(state, dict): 169 return _syck.Map(state.copy(), 170 tag="tag:python.yaml.org,2002:object:"+class_name) 171 value = {} 172 if args: 173 value['args'] = list(args) 174 if state or not isinstance(state, dict): 175 value['state'] = state 176 return _syck.Map(value, 177 tag="tag:python.yaml.org,2002:new:"+class_name) 178 179 def represent_object(self, object): # Do you understand this? I don't. 180 cls = type(object) 181 class_name = '%s.%s' % (cls.__module__, cls.__name__) 182 args = () 183 state = {} 184 if cls.__reduce__ is type.__reduce__: 185 if hasattr(object, '__reduce_ex__'): 186 reduce = object.__reduce_ex__(2) 187 args = reduce[1][1:] 188 else: 189 reduce = object.__reduce__() 190 if len(reduce) > 2: 191 state = reduce[2] 192 if state is None: 193 state = {} 194 if not args and isinstance(state, dict): 195 return _syck.Map(state.copy(), 196 tag="tag:python.yaml.org,2002:object:"+class_name) 197 if not state and isinstance(state, dict): 198 return _syck.Seq(list(args), 199 tag="tag:python.yaml.org,2002:new:"+class_name) 200 value = {} 201 if args: 202 value['args'] = list(args) 203 if state or not isinstance(state, dict): 204 value['state'] = state 205 return _syck.Map(value, 206 tag="tag:python.yaml.org,2002:new:"+class_name) 207 else: 208 reduce = object.__reduce__() 209 cls = reduce[0] 210 class_name = '%s.%s' % (cls.__module__, cls.__name__) 211 args = reduce[1] 212 state = None 213 if len(reduce) > 2: 214 state = reduce[2] 215 if state is None: 216 state = {} 217 if not state and isinstance(state, dict): 218 return _syck.Seq(list(args), 219 tag="tag:python.yaml.org,2002:apply:"+class_name) 220 value = {} 221 if args: 222 value['args'] = list(args) 223 if state or not isinstance(state, dict): 224 value['state'] = state 225 return _syck.Map(value, 226 tag="tag:python.yaml.org,2002:apply:"+class_name) 227 228 def represent__syck_Node(self, object): 229 object_type = type(object) 230 type_name = '%s.%s' % (object_type.__module__, object_type.__name__) 231 state = [] 232 if hasattr(object_type, '__slotnames__'): 233 for name in object_type.__slotnames__: 234 value = getattr(object, name) 235 if value: 236 state.append((name, value)) 237 return _syck.Map(state, 238 tag="tag:python.yaml.org,2002:object:"+type_name) 239 109 240 def allow_aliases(self, object): 241 """Checks whether the given object can be aliased.""" 110 242 if object is None or type(object) in [int, bool, float]: 111 243 return False 112 244 if type(object) is str and (not object or object.isalnum()): 113 245 return False 246 if type(object) is tuple and not object: 247 return False 114 248 return True 115 249 116 def emit(node, output=None, **parameters): 250 def emit(node, output=None, Dumper=Dumper, **parameters): 251 """ 252 Emits the given node to the output. 253 254 If output is None, returns the produced YAML document. 255 """ 117 256 if output is None: 118 257 dumper = Dumper(StringIO.StringIO(), **parameters) … … 123 262 return dumper.output.getvalue() 124 263 125 def dump(object, output=None, **parameters): 264 def dump(object, output=None, Dumper=Dumper, **parameters): 265 """ 266 Dumps the given object to the output. 267 268 If output is None, returns the produced YAML document. 269 """ 126 270 if output is None: 127 271 dumper = Dumper(StringIO.StringIO(), **parameters) … … 132 276 return dumper.output.getvalue() 133 277 134 def emit_documents(nodes, output=None, **parameters): 278 def emit_documents(nodes, output=None, Dumper=Dumper, **parameters): 279 """ 280 Emits the list of nodes to the output. 281 282 If output is None, returns the produced YAML document. 283 """ 135 284 if output is None: 136 285 dumper = Dumper(StringIO.StringIO(), **parameters) … … 142 291 return dumper.output.getvalue() 143 292 144 def dump_documents(objects, output=None, **parameters): 293 def dump_documents(objects, output=None, Dumper=Dumper, **parameters): 294 """ 295 Dumps the list of objects to the output. 296 297 If output is None, returns the produced YAML document. 298 """ 145 299 if output is None: 146 300 dumper = Dumper(StringIO.StringIO(), **parameters) -
/trunk/setup.py
r3 r27 1 2 NAME = 'PySyck' 3 VERSION = '0.55.1' 4 DESCRIPTION = "Python bindings for the Syck YAML parser and emitter" 5 LONG_DESCRIPTION = """\ 6 YAML is a data serialization format designed for human readability 7 and interaction with scripting languages. Syck is an extension for 8 reading and writing YAML in scripting languages. PySyck is aimed to 9 update the current Python bindings for Syck.""" 10 AUTHOR = "Kirill Simonov" 11 AUTHOR_EMAIL = 'xi@resolvent.net' 12 LICENSE = "BSD" 13 PLATFORMS = "Any" 14 URL = "http://xitology.org/pysyck/" 15 DOWNLOAD_URL = URL + "%s-%s.tar.gz" % (NAME, VERSION) 16 CLASSIFIERS = [ 17 "Development Status :: 3 - Alpha", 18 "Intended Audience :: Developers", 19 "License :: OSI Approved :: BSD License", 20 "Programming Language :: Python", 21 "Topic :: Software Development :: Libraries :: Python Modules", 22 "Topic :: Text Processing :: Markup", 23 ] 1 24 2 25 from distutils.core import setup, Extension … … 12 35 13 36 setup( 14 name='Syck', 15 version='0.55.1', 37 name=NAME, 38 version=VERSION, 39 description=DESCRIPTION, 40 long_description=LONG_DESCRIPTION, 41 author=AUTHOR, 42 author_email=AUTHOR_EMAIL, 43 license=LICENSE, 44 platforms=PLATFORMS, 45 url=URL, 46 download_url=DOWNLOAD_URL, 47 classifiers=CLASSIFIERS, 48 16 49 package_dir={'': 'lib'}, 17 50 packages=['syck'], … … 23 56 ), 24 57 ], 25 description="Python bindings for the Syck YAML parser",26 author="Kirill Simonov",27 author_email="xi@resolvent.net",28 license="BSD",29 url="http://xitology.org/python-syck/",30 download_url="http://xitology.org/*FIXME*",31 classifiers=[32 "Development Status :: 2 - Pre-Alpha",33 "Intended Audience :: Developers",34 "License :: OSI Approved :: BSD License",35 "Programming Language :: Python",36 "Topic :: Software Development :: Libraries :: Python Modules",37 "Topic :: Text Processing :: Markup",38 ],39 58 ) 40 59 -
/trunk/Makefile
r4 r29 1 1 2 .PHONY: default build force install test clean 2 .PHONY: default build force install test clean \ 3 dist-src dist-win dist-win-2.2 dist-win-2.3 dist-win-2.4 3 4 4 5 PYTHON=/usr/bin/python 6 REST2HTML=/usr/bin/rest2html --embed-stylesheet --stylesheet-path=/usr/share/python-docutils/stylesheets/default.css 5 7 TEST= 8 PARAMETERS= 6 9 7 default: build 10 default: build README.html 8 11 9 12 build: 10 ${PYTHON} setup.py build 13 ${PYTHON} setup.py build ${PARAMETERS} 11 14 12 15 force: 13 ${PYTHON} setup.py build -f 16 ${PYTHON} setup.py build -f ${PARAMETERS} 14 17 15 18 install: build 16 ${PYTHON} setup.py install 19 ${PYTHON} setup.py install ${PARAMETERS} 17 20 18 21 test: build … … 22 25 ${PYTHON} setup.py clean -a 23 26 27 dist-src: 28 ${PYTHON} setup.py sdist --formats=zip,gztar 29 30 dist-win: dist-win-2.2 dist-win-2.3 dist-win-2.4 31 32 dist-win-2.2: PYTHON=/c/Python22/python 33 dist-win-2.2: PARAMETERS=--compiler=mingw32 34 dist-win-2.2: 35 ${PYTHON} setup.py build ${PARAMETERS} 36 ${PYTHON} setup.py bdist_wininst 37 38 dist-win-2.3: PYTHON=/c/Python23/python 39 dist-win-2.3: PARAMETERS=--compiler=mingw32 40 dist-win-2.3: 41 ${PYTHON} setup.py build ${PARAMETERS} 42 ${PYTHON} setup.py bdist_wininst --skip-build --target-version=2.3 43 44 dist-win-2.4: PYTHON=/c/Python24/python 45 dist-win-2.4: PARAMETERS=--compiler=mingw32 46 dist-win-2.4: 47 ${PYTHON} setup.py build ${PARAMETERS} 48 ${PYTHON} setup.py bdist_wininst --skip-build --target-version=2.4 49 50 README.html: README.txt 51 ${REST2HTML} README.txt README.html 52 -
/trunk/sandbox/emit-it/emit-it.c
r17 r25 16 16 { 17 17 switch (id) { 18 /* 18 19 case 1: 19 20 syck_emit_seq(e, "tag:domainmyseq.tld,2002:zz", seq_none); … … 21 22 syck_emit_item(e, 3); 22 23 syck_emit_item(e, 4); 23 /* syck_emit_item(e, 2);24 syck_emit_item(e, 1);*/25 24 syck_emit_end(e); 26 25 break; … … 34 33 syck_emit_scalar(e, "x-private:myowntype", scalar_none, 0, 0, 0, "Ken Griffey", strlen("Ken Griffey")); 35 34 break; 35 */ 36 37 case 1: 38 syck_emit_map(e, NULL, map_none); 39 syck_emit_item(e, 2); 40 syck_emit_item(e, 3); 41 syck_emit_end(e); 42 break; 43 44 case 2: 45 syck_emit_map(e, "x-private:key", map_none); 46 syck_emit_item(e, 4); 47 syck_emit_item(e, 5); 48 syck_emit_end(e); 49 break; 50 51 case 3: 52 case 4: 53 case 5: 54 syck_emit_scalar(e, NULL, scalar_none, 0, 0, 0, "foo", 3); 55 break; 36 56 } 57 37 58 } 38 59 … … 48 69 syck_emitter_mark_node(e, 3); 49 70 syck_emitter_mark_node(e, 4); 71 syck_emitter_mark_node(e, 5); 50 72 /* syck_emitter_mark_node(e, 2); 51 73 syck_emitter_mark_node(e, 1);*/ -
/trunk/sandbox/emit-it/Makefile
r11 r25 1 2 ALL = emit-it complex-key-bug trailing-space-bug 1 3 2 4 .PHONY: default clean 3 5 4 default: emit-it6 default: $(ALL) 5 7 6 8 clean: 7 rm -f emit-it8 rm -f emit-it.o9 rm -f *.o 10 rm -f $(ALL) 9 11 10 emit-it: emit-it.o 11 gcc emit-it.o -o emit-it -lsyck -L${HOME}/lib -Wall -Wstrict-prototypes12 %.o: %.c 13 gcc -c $< -o $@ -Wall -Wstrict-prototypes -I${HOME}/include 12 14 13 emit-it.o: emit-it.c 14 gcc -c emit-it.c -o emit-it.o -I${HOME}/include 15 15 $(ALL): %: %.o 16 gcc $< -o $@ -lsyck -L${HOME}/lib -Wall -Wstrict-prototypes -
/trunk/ext/_syckmodule.c
r20 r25 43 43 PyDoc_STRVAR(PySyckNode_doc, 44 44 "_syck.Node() -> TypeError\n\n" 45 "_syck.Node is an abstract type. It is abase type for _syck.Scalar,\n"45 "_syck.Node is an abstract type. It is the base type for _syck.Scalar,\n" 46 46 "_syck.Seq, and _syck.Map. You cannot create an instance of _syck.Node\n" 47 47 "directly. You may use _syck.Node for type checking or subclassing.\n"); … … 220 220 " -> a Scalar node\n\n" 221 221 "_syck.Scalar represents a scalar node in Syck parser and emitter\n" 222 " graphs. A scalar node points to a single string value.\n");222 "trees. A scalar node points to a single string value.\n"); 223 223 224 224 typedef struct { … … 549 549 "Seq(value=[], tag=None, inline=False) -> a Seq node\n\n" 550 550 "_syck.Seq represents a sequence node in Syck parser and emitter\n" 551 " graphs. A sequence node points to an ordered set of subnodes.\n");551 "trees. A sequence node points to an ordered set of subnodes.\n"); 552 552 553 553 typedef struct { … … 718 718 719 719 PyDoc_STRVAR(PySyckMap_doc, 720 "Map(value= '', tag=None, inline=False) -> a Map node\n\n"720 "Map(value={}, tag=None, inline=False) -> a Map node\n\n" 721 721 "_syck.Map represents a mapping node in Syck parser and emitter\n" 722 " graphs. A mapping node points to an unordered collections of pairs.\n");722 "trees. A mapping node points to an unordered collections of pairs.\n"); 723 723 724 724 typedef struct { … … 833 833 PyDoc_STR("the node kind, always 'map', read-only"), &PySyck_MapKind}, 834 834 {"value", (getter)PySyckNode_getvalue, (setter)PySyckMap_setvalue, 835 PyDoc_STR("the node value, a mapping"), NULL},835 PyDoc_STR("the node value, a list of pairs or a dictionary"), NULL}, 836 836 {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag, 837 837 PyDoc_STR("the node tag, a string or None"), NULL}, … … 893 893 " -> a Parser object\n\n" 894 894 "_syck.Parser is a low-lever wrapper of the Syck parser. It parses\n" 895 "a YAML stream and produces a graphof Nodes.\n");895 "a YAML stream and produces a tree of Nodes.\n"); 896 896 897 897 typedef struct { … … 1017 1017 static PyGetSetDef PySyckParser_getsetters[] = { 1018 1018 {"source", (getter)PySyckParser_getsource, NULL, 1019 PyDoc_STR("IO source, a string or file-like object"), NULL},1019 PyDoc_STR("IO source, a string or a file-like object"), NULL}, 1020 1020 {"implicit_typing", (getter)PySyckParser_getimplicit_typing, NULL, 1021 1021 PyDoc_STR("implicit typing of builtin YAML types"), NULL}, … … 1253 1253 1254 1254 if (self->parsing) { 1255 PyErr_SetString(PyExc_RuntimeError, "do not call Parser.parse while it is already parsing"); 1255 PyErr_SetString(PyExc_RuntimeError, 1256 "do not call Parser.parse while it is already running"); 1256 1257 return NULL; 1257 1258 } … … 1292 1293 PyDoc_STRVAR(PySyckParser_parse_doc, 1293 1294 "parse() -> the root Node object\n\n" 1294 "Parses the source and returns the next document. On EOF, returns None\n" 1295 "and sets the 'eof' attribute on.\n"); 1295 "Parses the source and returns the root of the Node tree. Call it\n" 1296 "several times to retrieve all documents from the source. On EOF,\n" 1297 "returns None and sets the 'eof' attribute on.\n"); 1296 1298 1297 1299 static PyMethodDef PySyckParser_methods[] = { … … 1348 1350 1349 1351 PyDoc_STRVAR(PySyckEmitter_doc, 1350 "Emitter(output, headless=False, use_header=True, explicit_typing=True," 1351 " style=None, best_width=80, indent=2) -> an Emitter object\n\n" 1352 "_syck.Emitter is a low-lever wrapper of the Syck emitter. It emit\n" 1352 "Emitter(output, headless=False, use_header=False, use_version=False,\n" 1353 " explicit_typing=True, style=None, best_width=80, indent=2)\n" 1354 " -> an Emitter object\n\n" 1355 "_syck.Emitter is a low-lever wrapper of the Syck emitter. It emits\n" 1353 1356 "a tree of Nodes into a YAML stream.\n"); 1354 1357 … … 1530 1533 PyDoc_STR("headerless document flag"), NULL}, 1531 1534 {"use_header", (getter)PySyckEmitter_getuse_header, NULL, 1532 PyDoc_STR("force header "), NULL},1535 PyDoc_STR("force header flag"), NULL}, 1533 1536 {"use_version", (getter)PySyckEmitter_getuse_version, NULL, 1534 PyDoc_STR("force version "), NULL},1537 PyDoc_STR("force version flag"), NULL}, 1535 1538 {"explicit_typing", (getter)PySyckEmitter_getexplicit_typing, NULL, 1536 1539 PyDoc_STR("explicit typing for all collections"), NULL}, … … 1752 1755 Py_INCREF(output); 1753 1756 self->output = output; 1754 1755 /*1756 self->emitter = syck_new_emitter();1757 self->emitter->bonus = self;1758 self->emitter->headless = self->headless;1759 self->emitter->use_header = use_header;1760 self->emitter->use_version = use_version;1761 self->emitter->explicit_typing = explicit_typing;1762 self->emitter->style = self->style;1763 self->emitter->best_width = self->best_width;1764 self->emitter->indent = self->indent;1765 1766 syck_emitter_handler(self->emitter, PySyckEmitter_node_handler);1767 syck_output_handler(self->emitter, PySyckEmitter_write_handler);1768 */1769 1757 1770 1758 self->emitting = 0; … … 1974 1962 PyDoc_STRVAR(PySyckEmitter_emit_doc, 1975 1963 "emit(root_node) -> None\n\n" 1976 "Emit the Node tree to the output.\n");1964 "Emits the Node tree to the output.\n"); 1977 1965 1978 1966 static PyMethodDef PySyckEmitter_methods[] = { … … 2033 2021 2034 2022 PyDoc_STRVAR(PySyck_doc, 2035 "low-level wrapper for the Syck YAML parser and emitter"); 2023 "_syck is a low-level wrapper for the Syck YAML parser and emitter.\n" 2024 "Do not use it directly, use the module 'syck' instead.\n"); 2025 2026 static int 2027 add_slotnames(PyTypeObject *type) 2028 { 2029 PyObject *slotnames; 2030 PyObject *name; 2031 PyGetSetDef *getsetter; 2032 2033 if (!type->tp_getset) return 0; 2034 if (!type->tp_dict) return 0; 2035 2036 slotnames = PyList_New(0); 2037 if (!slotnames) return -1; 2038 2039 for (getsetter = type->tp_getset; getsetter->name; getsetter++) { 2040 if (!getsetter->set) continue; 2041 name = PyString_FromString(getsetter->name); 2042 if (!name) { 2043 Py_DECREF(slotnames); 2044 return -1; 2045 } 2046 if (PyList_Append(slotnames, name) < 0) { 2047 Py_DECREF(name); 2048 Py_DECREF(slotnames); 2049 return -1; 2050 } 2051 Py_DECREF(name); 2052 } 2053 2054 if (PyDict_SetItemString(type->tp_dict, "__slotnames__", slotnames) < 0) { 2055 Py_DECREF(slotnames); 2056 return -1; 2057 } 2058 2059 Py_DECREF(slotnames); 2060 return 0; 2061 } 2036 2062 2037 2063 PyMODINIT_FUNC … … 2044 2070 if (PyType_Ready(&PySyckScalar_Type) < 0) 2045 2071 return; 2072 if (add_slotnames(&PySyckScalar_Type) < 0) 2073 return; 2046 2074 if (PyType_Ready(&PySyckSeq_Type) < 0) 2047 2075 return; 2076 if (add_slotnames(&PySyckSeq_Type) < 0) 2077 return; 2048 2078 if (PyType_Ready(&PySyckMap_Type) < 0) 2079 return; 2080 if (add_slotnames(&PySyckMap_Type) < 0) 2049 2081 return; 2050 2082 if (PyType_Ready(&PySyckParser_Type) < 0) -
/trunk/tests/test_loader.py
r20 r23 136 136 """ 137 137 138 MUTABLE_KEY = """ 139 ? [] 140 : [] 141 """ 142 138 143 class TestDocuments(test_parser.TestDocuments): 139 144 … … 181 186 182 187 def _testFileValues(self, (source, structure)): 183 filename = os.tempnam('/tmp', '_syck_test_') 184 file(filename, 'wb').write(source) 185 try: 186 self.assertEqualStructure(syck.parse(file(filename)), structure) 187 self.assertEqual(syck.load(file(filename)), structure) 188 except: 189 os.remove(filename) 190 raise 188 tempfile = os.tmpfile() 189 tempfile.write(source) 190 tempfile.seek(0) 191 self.assertEqualStructure(syck.parse(tempfile), structure) 192 tempfile.seek(0) 193 self.assertEqual(syck.load(tempfile), structure) 194 tempfile.seek(0) 191 195 192 196 class TestImplicitScalars(unittest.TestCase): … … 202 206 203 207 def testFloat(self): 204 self.assert AlmostEqual(syck.load('6.8523015e+5'), 685230.15)208 self.assertEqual(syck.load('6.8523015e+5'), 685230.15) 205 209 # Syck does not understand '_'. 206 210 #self.assertAlmostEqual(syck.load('685.230_15e+03'), 685230.15) 207 211 #self.assertAlmostEqual(syck.load('685_230.15'), 685230.15) 208 self.assert AlmostEqual(syck.load('685.23015e+03'), 685230.15)209 self.assert AlmostEqual(syck.load('685230.15'), 685230.15)210 self.assert AlmostEqual(syck.load('190:20:30.15'), 685230.15)211 self.assertEqual( syck.load('-.inf'), -INF)212 self.assertEqual( syck.load('.nan'), NAN)212 self.assertEqual(syck.load('685.23015e+03'), 685230.15) 213 self.assertEqual(syck.load('685230.15'), 685230.15) 214 self.assertEqual(syck.load('190:20:30.15'), 685230.15) 215 self.assertEqual(repr(syck.load('-.inf')), repr(-INF)) 216 self.assertEqual(repr(syck.load('.nan')), repr(NAN)) 213 217 214 218 def testInteger(self): … … 268 272 node = syck.parse(ALIASES) 269 273 values = node.value.values() 270 print values271 print id(values[0])272 print id(values[1])273 274 self.assert_(values[0] is values[1]) 274 275 … … 277 278 self.assert_(document['foo'] is document['bar']) 278 279 280 class TestMutableKey(unittest.TestCase): 281 282 def testMutableKey(self): 283 document = syck.load(MUTABLE_KEY) 284 self.assertEqual(type(document), list) 285 self.assertEqual(len(document), 1) 286 self.assertEqual(type(document[0]), tuple) 287 self.assertEqual(len(document[0]), 2) 288 self.assertEqual(document[0][0], document[0][1]) -
/trunk/tests/test_emitter.py
r17 r23 163 163 emitter = _syck.Emitter(StringIO.StringIO(), headless=False) 164 164 emitter.emit(CYCLE) 165 self.assert_( '---' in emitter.output.getvalue())165 self.assert_(emitter.output.getvalue().find('---') != -1) 166 166 emitter = _syck.Emitter(StringIO.StringIO(), headless=True) 167 167 emitter.emit(CYCLE) 168 self.assert_( '---' not in emitter.output.getvalue())168 self.assert_(emitter.output.getvalue().find('---') == -1) 169 169 170 170 def testUseHeader(self): 171 171 emitter = _syck.Emitter(StringIO.StringIO(), headless=True) 172 172 emitter.emit(EXAMPLE) 173 self.assert_( '---' not in emitter.output.getvalue())173 self.assert_(emitter.output.getvalue().find('---') == -1) 174 174 emitter = _syck.Emitter(StringIO.StringIO(), use_header=True) 175 175 emitter.emit(EXAMPLE) 176 self.assert_( '---' in emitter.output.getvalue())176 self.assert_(emitter.output.getvalue().find('---') != -1) 177 177 178 178 def testExplicitTyping(self): … … 235 235 document = parser.parse() 236 236 self.assertEqual(len(document.value), len(TAGS)) 237 for index, node in enumerate(document.value): 237 for index in range(len(document.value)): 238 node = document.value[index] 238 239 self.assertEqual(node.tag, TAGS[index]) 239 240 … … 282 283 283 284 284 class TestSyckBugWithTrailingSpace(unittest.TestCase):285 286 def testSyckBugWithTrailingSpace(self):287 emitter = _syck.Emitter(StringIO.StringIO())288 emitter.emit(_syck.Scalar('foo ', tag="tag:yaml.org,2002:str"))289 parser = _syck.Parser(emitter.output.getvalue())290 self.assertEqual(parser.parse().value, 'foo ')291 292 285 #class TestSyckBugWithTrailingSpace(unittest.TestCase): 286 # 287 # def testSyckBugWithTrailingSpace(self): 288 # emitter = _syck.Emitter(StringIO.StringIO()) 289 # emitter.emit(_syck.Scalar('foo ', tag="tag:yaml.org,2002:str")) 290 # parser = _syck.Parser(emitter.output.getvalue()) 291 # self.assertEqual(parser.parse().value, 'foo ') 292 293 -
/trunk/tests/test_syck.py
r20 r21 2 2 import unittest 3 3 4 #from test_node import *4 from test_node import * 5 5 from test_parser import * 6 6 from test_loader import * 7 7 from test_emitter import * 8 8 from test_dumper import * 9 from test_pickle import * 9 10 10 11 def main(module='__main__'): -
/trunk/tests/test_dumper.py
r20 r23 1 2 from __future__ import generators 1 3 2 4 import unittest 3 5 import syck 4 import StringIO , datetime, sets6 import StringIO 5 7 import test_emitter 8 9 try: 10 import datetime 11 except: 12 class _datetime: 13 def datetime(self, *args): 14 return args 15 datetime = _datetime() 16 17 try: 18 import sets 19 except: 20 class _sets: 21 def Set(self, items): 22 set = {} 23 for items in items: 24 set[items] = None 25 return set 26 sets = _sets() 27 6 28 7 29 EXAMPLE = { … … 136 158 for a, b in zip(scalars, SCALARS): 137 159 self.assertEqual(type(a), type(b)) 138 self.assertEqual(a, b) 160 if type(a) is float: 161 self.assertEqual(repr(a), repr(b)) 162 else: 163 self.assertEqual(a, b) 139 164 140 165 class TestCollectionTypes(unittest.TestCase): -
/trunk/tests/test_parser.py
r20 r23 227 227 self.assertEqual(type(structure), list) 228 228 self.assertEqual(len(node.value), len(structure)) 229 for i, item in enumerate(node.value): 229 for i in range(len(node.value)): 230 item = node.value[i] 230 231 self.assertEqualStructure(item, structure[i]) 231 232 elif node.kind == 'map':
Note: See TracChangeset
for help on using the changeset viewer.
