-
diff --git lib/yaml/__init__.py lib/yaml/__init__.py
index e131795..2a568a3 100644
|
|
|
|
| | 1 | import io |
| 1 | 2 | |
| 2 | | from error import * |
| | 3 | from yaml.error import * |
| 3 | 4 | |
| 4 | | from tokens import * |
| 5 | | from events import * |
| 6 | | from nodes import * |
| | 5 | from yaml.tokens import * |
| | 6 | from yaml.events import * |
| | 7 | from yaml.nodes import * |
| 7 | 8 | |
| 8 | | from loader import * |
| 9 | | from dumper import * |
| | 9 | from yaml.loader import * |
| | 10 | from yaml.dumper import * |
| 10 | 11 | |
| 11 | 12 | try: |
| 12 | | from cyaml import * |
| | 13 | from yaml.cyaml import * |
| 13 | 14 | except ImportError: |
| 14 | 15 | pass |
| 15 | 16 | |
| … |
… |
def emit(events, stream=None, Dumper=Dumper, |
| 88 | 89 | """ |
| 89 | 90 | getvalue = None |
| 90 | 91 | if stream is None: |
| 91 | | try: |
| 92 | | from cStringIO import StringIO |
| 93 | | except ImportError: |
| 94 | | from StringIO import StringIO |
| 95 | | stream = StringIO() |
| | 92 | stream = io.StringIO() |
| 96 | 93 | getvalue = stream.getvalue |
| 97 | 94 | dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, |
| 98 | 95 | allow_unicode=allow_unicode, line_break=line_break) |
| … |
… |
def serialize_all(nodes, stream=None, Dumper=Dumper, |
| 112 | 109 | """ |
| 113 | 110 | getvalue = None |
| 114 | 111 | if stream is None: |
| 115 | | try: |
| 116 | | from cStringIO import StringIO |
| 117 | | except ImportError: |
| 118 | | from StringIO import StringIO |
| 119 | | stream = StringIO() |
| | 112 | stream = io.StringIO() |
| 120 | 113 | getvalue = stream.getvalue |
| 121 | 114 | dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, |
| 122 | 115 | allow_unicode=allow_unicode, line_break=line_break, |
| … |
… |
def dump_all(documents, stream=None, Dumper=Dumper, |
| 148 | 141 | """ |
| 149 | 142 | getvalue = None |
| 150 | 143 | if stream is None: |
| 151 | | try: |
| 152 | | from cStringIO import StringIO |
| 153 | | except ImportError: |
| 154 | | from StringIO import StringIO |
| 155 | | stream = StringIO() |
| | 144 | stream = io.StringIO() |
| 156 | 145 | getvalue = stream.getvalue |
| 157 | 146 | dumper = Dumper(stream, default_style=default_style, |
| 158 | 147 | default_flow_style=default_flow_style, |
| … |
… |
class YAMLObjectMetaclass(type): |
| 256 | 245 | cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) |
| 257 | 246 | cls.yaml_dumper.add_representer(cls, cls.to_yaml) |
| 258 | 247 | |
| 259 | | class YAMLObject(object): |
| | 248 | class YAMLObject(metaclass=YAMLObjectMetaclass): |
| 260 | 249 | """ |
| 261 | 250 | An object that can dump itself to a YAML stream |
| 262 | 251 | and load itself from a YAML stream. |
| 263 | 252 | """ |
| 264 | 253 | |
| 265 | | __metaclass__ = YAMLObjectMetaclass |
| 266 | 254 | __slots__ = () # no direct instantiation, so allow immutable subclasses |
| 267 | 255 | |
| 268 | 256 | yaml_loader = Loader |
-
diff --git lib/yaml/composer.py lib/yaml/composer.py
index 06e5ac7..f468cc5 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['Composer', 'ComposerError'] |
| 3 | 3 | |
| 4 | | from error import MarkedYAMLError |
| 5 | | from events import * |
| 6 | | from nodes import * |
| | 4 | from yaml.error import MarkedYAMLError |
| | 5 | from yaml.events import * |
| | 6 | from yaml.nodes import * |
| 7 | 7 | |
| 8 | 8 | class ComposerError(MarkedYAMLError): |
| 9 | 9 | pass |
| 10 | 10 | |
| 11 | | class Composer(object): |
| | 11 | class Composer: |
| 12 | 12 | |
| 13 | 13 | def __init__(self): |
| 14 | 14 | self.anchors = {} |
| … |
… |
class Composer(object): |
| 88 | 88 | def compose_scalar_node(self, anchor): |
| 89 | 89 | event = self.get_event() |
| 90 | 90 | tag = event.tag |
| 91 | | if tag is None or tag == u'!': |
| | 91 | if tag is None or tag == '!': |
| 92 | 92 | tag = self.resolve(ScalarNode, event.value, event.implicit) |
| 93 | 93 | node = ScalarNode(tag, event.value, |
| 94 | 94 | event.start_mark, event.end_mark, style=event.style) |
| … |
… |
class Composer(object): |
| 99 | 99 | def compose_sequence_node(self, anchor): |
| 100 | 100 | start_event = self.get_event() |
| 101 | 101 | tag = start_event.tag |
| 102 | | if tag is None or tag == u'!': |
| | 102 | if tag is None or tag == '!': |
| 103 | 103 | tag = self.resolve(SequenceNode, None, start_event.implicit) |
| 104 | 104 | node = SequenceNode(tag, [], |
| 105 | 105 | start_event.start_mark, None, |
| … |
… |
class Composer(object): |
| 117 | 117 | def compose_mapping_node(self, anchor): |
| 118 | 118 | start_event = self.get_event() |
| 119 | 119 | tag = start_event.tag |
| 120 | | if tag is None or tag == u'!': |
| | 120 | if tag is None or tag == '!': |
| 121 | 121 | tag = self.resolve(MappingNode, None, start_event.implicit) |
| 122 | 122 | node = MappingNode(tag, [], |
| 123 | 123 | start_event.start_mark, None, |
-
diff --git lib/yaml/constructor.py lib/yaml/constructor.py
index 34cc226..cb51483 100644
|
|
|
|
| 2 | 2 | __all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor', |
| 3 | 3 | 'ConstructorError'] |
| 4 | 4 | |
| 5 | | from error import * |
| 6 | | from nodes import * |
| | 5 | from yaml.error import * |
| | 6 | from yaml.nodes import * |
| 7 | 7 | |
| 8 | 8 | import datetime |
| 9 | 9 | |
| 10 | | try: |
| 11 | | set |
| 12 | | except NameError: |
| 13 | | from sets import Set as set |
| 14 | | |
| 15 | | import binascii, re, sys, types |
| | 10 | import binascii, re, sys, types, base64 |
| 16 | 11 | |
| 17 | 12 | class ConstructorError(MarkedYAMLError): |
| 18 | 13 | pass |
| 19 | 14 | |
| 20 | | class BaseConstructor(object): |
| | 15 | class BaseConstructor: |
| 21 | 16 | |
| 22 | 17 | yaml_constructors = {} |
| 23 | 18 | yaml_multi_constructors = {} |
| … |
… |
class BaseConstructor(object): |
| 96 | 91 | data = constructor(self, tag_suffix, node) |
| 97 | 92 | if isinstance(data, types.GeneratorType): |
| 98 | 93 | generator = data |
| 99 | | data = generator.next() |
| | 94 | data = next(generator) |
| 100 | 95 | if self.deep_construct: |
| 101 | 96 | for dummy in generator: |
| 102 | 97 | pass |
| … |
… |
class BaseConstructor(object): |
| 133 | 128 | key = self.construct_object(key_node, deep=deep) |
| 134 | 129 | try: |
| 135 | 130 | hash(key) |
| 136 | | except TypeError, exc: |
| | 131 | except TypeError as exc: |
| 137 | 132 | raise ConstructorError("while constructing a mapping", node.start_mark, |
| 138 | 133 | "found unacceptable key (%s)" % exc, key_node.start_mark) |
| 139 | 134 | value = self.construct_object(value_node, deep=deep) |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 169 | 164 | def construct_scalar(self, node): |
| 170 | 165 | if isinstance(node, MappingNode): |
| 171 | 166 | for key_node, value_node in node.value: |
| 172 | | if key_node.tag == u'tag:yaml.org,2002:value': |
| | 167 | if key_node.tag == 'tag:yaml.org,2002:value': |
| 173 | 168 | return self.construct_scalar(value_node) |
| 174 | 169 | return BaseConstructor.construct_scalar(self, node) |
| 175 | 170 | |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 178 | 173 | index = 0 |
| 179 | 174 | while index < len(node.value): |
| 180 | 175 | key_node, value_node = node.value[index] |
| 181 | | if key_node.tag == u'tag:yaml.org,2002:merge': |
| | 176 | if key_node.tag == 'tag:yaml.org,2002:merge': |
| 182 | 177 | del node.value[index] |
| 183 | 178 | if isinstance(value_node, MappingNode): |
| 184 | 179 | self.flatten_mapping(value_node) |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 200 | 195 | raise ConstructorError("while constructing a mapping", node.start_mark, |
| 201 | 196 | "expected a mapping or list of mappings for merging, but found %s" |
| 202 | 197 | % value_node.id, value_node.start_mark) |
| 203 | | elif key_node.tag == u'tag:yaml.org,2002:value': |
| 204 | | key_node.tag = u'tag:yaml.org,2002:str' |
| | 198 | elif key_node.tag == 'tag:yaml.org,2002:value': |
| | 199 | key_node.tag = 'tag:yaml.org,2002:str' |
| 205 | 200 | index += 1 |
| 206 | 201 | else: |
| 207 | 202 | index += 1 |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 218 | 213 | return None |
| 219 | 214 | |
| 220 | 215 | bool_values = { |
| 221 | | u'yes': True, |
| 222 | | u'no': False, |
| 223 | | u'true': True, |
| 224 | | u'false': False, |
| 225 | | u'on': True, |
| 226 | | u'off': False, |
| | 216 | 'yes': True, |
| | 217 | 'no': False, |
| | 218 | 'true': True, |
| | 219 | 'false': False, |
| | 220 | 'on': True, |
| | 221 | 'off': False, |
| 227 | 222 | } |
| 228 | 223 | |
| 229 | 224 | def construct_yaml_bool(self, node): |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 290 | 285 | def construct_yaml_binary(self, node): |
| 291 | 286 | value = self.construct_scalar(node) |
| 292 | 287 | try: |
| 293 | | return str(value).decode('base64') |
| 294 | | except (binascii.Error, UnicodeEncodeError), exc: |
| | 288 | return base64.decodestring(value.encode('utf-8')) |
| | 289 | except (binascii.Error, UnicodeEncodeError) as exc: |
| 295 | 290 | raise ConstructorError(None, None, |
| 296 | 291 | "failed to decode base64 data: %s" % exc, node.start_mark) |
| 297 | 292 | |
| 298 | 293 | timestamp_regexp = re.compile( |
| 299 | | ur'''^(?P<year>[0-9][0-9][0-9][0-9]) |
| | 294 | r'''^(?P<year>[0-9][0-9][0-9][0-9]) |
| 300 | 295 | -(?P<month>[0-9][0-9]?) |
| 301 | 296 | -(?P<day>[0-9][0-9]?) |
| 302 | 297 | (?:(?:[Tt]|[ \t]+) |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 387 | 382 | data.update(value) |
| 388 | 383 | |
| 389 | 384 | def construct_yaml_str(self, node): |
| 390 | | value = self.construct_scalar(node) |
| 391 | | try: |
| 392 | | return value.encode('ascii') |
| 393 | | except UnicodeEncodeError: |
| 394 | | return value |
| | 385 | return self.construct_scalar(node) |
| 395 | 386 | |
| 396 | 387 | def construct_yaml_seq(self, node): |
| 397 | 388 | data = [] |
| … |
… |
class SafeConstructor(BaseConstructor): |
| 416 | 407 | |
| 417 | 408 | def construct_undefined(self, node): |
| 418 | 409 | raise ConstructorError(None, None, |
| 419 | | "could not determine a constructor for the tag %r" % node.tag.encode('utf-8'), |
| | 410 | "could not determine a constructor for the tag %r" % node.tag, |
| 420 | 411 | node.start_mark) |
| 421 | 412 | |
| 422 | 413 | SafeConstructor.add_constructor( |
| 423 | | u'tag:yaml.org,2002:null', |
| | 414 | 'tag:yaml.org,2002:null', |
| 424 | 415 | SafeConstructor.construct_yaml_null) |
| 425 | 416 | |
| 426 | 417 | SafeConstructor.add_constructor( |
| 427 | | u'tag:yaml.org,2002:bool', |
| | 418 | 'tag:yaml.org,2002:bool', |
| 428 | 419 | SafeConstructor.construct_yaml_bool) |
| 429 | 420 | |
| 430 | 421 | SafeConstructor.add_constructor( |
| 431 | | u'tag:yaml.org,2002:int', |
| | 422 | 'tag:yaml.org,2002:int', |
| 432 | 423 | SafeConstructor.construct_yaml_int) |
| 433 | 424 | |
| 434 | 425 | SafeConstructor.add_constructor( |
| 435 | | u'tag:yaml.org,2002:float', |
| | 426 | 'tag:yaml.org,2002:float', |
| 436 | 427 | SafeConstructor.construct_yaml_float) |
| 437 | 428 | |
| 438 | 429 | SafeConstructor.add_constructor( |
| 439 | | u'tag:yaml.org,2002:binary', |
| | 430 | 'tag:yaml.org,2002:binary', |
| 440 | 431 | SafeConstructor.construct_yaml_binary) |
| 441 | 432 | |
| 442 | 433 | SafeConstructor.add_constructor( |
| 443 | | u'tag:yaml.org,2002:timestamp', |
| | 434 | 'tag:yaml.org,2002:timestamp', |
| 444 | 435 | SafeConstructor.construct_yaml_timestamp) |
| 445 | 436 | |
| 446 | 437 | SafeConstructor.add_constructor( |
| 447 | | u'tag:yaml.org,2002:omap', |
| | 438 | 'tag:yaml.org,2002:omap', |
| 448 | 439 | SafeConstructor.construct_yaml_omap) |
| 449 | 440 | |
| 450 | 441 | SafeConstructor.add_constructor( |
| 451 | | u'tag:yaml.org,2002:pairs', |
| | 442 | 'tag:yaml.org,2002:pairs', |
| 452 | 443 | SafeConstructor.construct_yaml_pairs) |
| 453 | 444 | |
| 454 | 445 | SafeConstructor.add_constructor( |
| 455 | | u'tag:yaml.org,2002:set', |
| | 446 | 'tag:yaml.org,2002:set', |
| 456 | 447 | SafeConstructor.construct_yaml_set) |
| 457 | 448 | |
| 458 | 449 | SafeConstructor.add_constructor( |
| 459 | | u'tag:yaml.org,2002:str', |
| | 450 | 'tag:yaml.org,2002:str', |
| 460 | 451 | SafeConstructor.construct_yaml_str) |
| 461 | 452 | |
| 462 | 453 | SafeConstructor.add_constructor( |
| 463 | | u'tag:yaml.org,2002:seq', |
| | 454 | 'tag:yaml.org,2002:seq', |
| 464 | 455 | SafeConstructor.construct_yaml_seq) |
| 465 | 456 | |
| 466 | 457 | SafeConstructor.add_constructor( |
| 467 | | u'tag:yaml.org,2002:map', |
| | 458 | 'tag:yaml.org,2002:map', |
| 468 | 459 | SafeConstructor.construct_yaml_map) |
| 469 | 460 | |
| 470 | 461 | SafeConstructor.add_constructor(None, |
| … |
… |
SafeConstructor.add_constructor(None, |
| 473 | 464 | class Constructor(SafeConstructor): |
| 474 | 465 | |
| 475 | 466 | def construct_python_str(self, node): |
| 476 | | return self.construct_scalar(node).encode('utf-8') |
| | 467 | return self.construct_scalar(node) |
| 477 | 468 | |
| 478 | 469 | def construct_python_unicode(self, node): |
| 479 | 470 | return self.construct_scalar(node) |
| 480 | 471 | |
| | 472 | def construct_python_bytes(self, node): |
| | 473 | return self.construct_scalar(node).encode('utf-8') |
| | 474 | |
| 481 | 475 | def construct_python_long(self, node): |
| 482 | | return long(self.construct_yaml_int(node)) |
| | 476 | return self.construct_yaml_int(node) |
| 483 | 477 | |
| 484 | 478 | def construct_python_complex(self, node): |
| 485 | 479 | return complex(self.construct_scalar(node)) |
| … |
… |
class Constructor(SafeConstructor): |
| 493 | 487 | "expected non-empty name appended to the tag", mark) |
| 494 | 488 | try: |
| 495 | 489 | __import__(name) |
| 496 | | except ImportError, exc: |
| | 490 | except ImportError as exc: |
| 497 | 491 | raise ConstructorError("while constructing a Python module", mark, |
| 498 | | "cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark) |
| | 492 | "cannot find module %r (%s)" % (name, exc), mark) |
| 499 | 493 | return sys.modules[name] |
| 500 | 494 | |
| 501 | 495 | def find_python_name(self, name, mark): |
| 502 | 496 | if not name: |
| 503 | 497 | raise ConstructorError("while constructing a Python object", mark, |
| 504 | 498 | "expected non-empty name appended to the tag", mark) |
| 505 | | if u'.' in name: |
| 506 | | # Python 2.4 only |
| 507 | | #module_name, object_name = name.rsplit('.', 1) |
| 508 | | items = name.split('.') |
| 509 | | object_name = items.pop() |
| 510 | | module_name = '.'.join(items) |
| | 499 | if '.' in name: |
| | 500 | module_name, object_name = name.rsplit('.', 1) |
| 511 | 501 | else: |
| 512 | | module_name = '__builtin__' |
| | 502 | module_name = 'builtins' |
| 513 | 503 | object_name = name |
| 514 | 504 | try: |
| 515 | 505 | __import__(module_name) |
| 516 | | except ImportError, exc: |
| | 506 | except ImportError as exc: |
| 517 | 507 | raise ConstructorError("while constructing a Python object", mark, |
| 518 | | "cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark) |
| | 508 | "cannot find module %r (%s)" % (module_name, exc), mark) |
| 519 | 509 | module = sys.modules[module_name] |
| 520 | 510 | if not hasattr(module, object_name): |
| 521 | 511 | raise ConstructorError("while constructing a Python object", mark, |
| 522 | | "cannot find %r in the module %r" % (object_name.encode('utf-8'), |
| | 512 | "cannot find %r in the module %r" % (object_name, |
| 523 | 513 | module.__name__), mark) |
| 524 | 514 | return getattr(module, object_name) |
| 525 | 515 | |
| … |
… |
class Constructor(SafeConstructor): |
| 527 | 517 | value = self.construct_scalar(node) |
| 528 | 518 | if value: |
| 529 | 519 | raise ConstructorError("while constructing a Python name", node.start_mark, |
| 530 | | "expected the empty value, but found %r" % value.encode('utf-8'), |
| | 520 | "expected the empty value, but found %r" % value, |
| 531 | 521 | node.start_mark) |
| 532 | 522 | return self.find_python_name(suffix, node.start_mark) |
| 533 | 523 | |
| … |
… |
class Constructor(SafeConstructor): |
| 535 | 525 | value = self.construct_scalar(node) |
| 536 | 526 | if value: |
| 537 | 527 | raise ConstructorError("while constructing a Python module", node.start_mark, |
| 538 | | "expected the empty value, but found %r" % value.encode('utf-8'), |
| | 528 | "expected the empty value, but found %r" % value, |
| 539 | 529 | node.start_mark) |
| 540 | 530 | return self.find_python_module(suffix, node.start_mark) |
| 541 | 531 | |
| 542 | | class classobj: pass |
| 543 | | |
| 544 | 532 | def make_python_instance(self, suffix, node, |
| 545 | 533 | args=None, kwds=None, newobj=False): |
| 546 | 534 | if not args: |
| … |
… |
class Constructor(SafeConstructor): |
| 548 | 536 | if not kwds: |
| 549 | 537 | kwds = {} |
| 550 | 538 | cls = self.find_python_name(suffix, node.start_mark) |
| 551 | | if newobj and isinstance(cls, type(self.classobj)) \ |
| 552 | | and not args and not kwds: |
| 553 | | instance = self.classobj() |
| 554 | | instance.__class__ = cls |
| 555 | | return instance |
| 556 | | elif newobj and isinstance(cls, type): |
| | 539 | if newobj and isinstance(cls, type): |
| 557 | 540 | return cls.__new__(cls, *args, **kwds) |
| 558 | 541 | else: |
| 559 | 542 | return cls(*args, **kwds) |
| … |
… |
class Constructor(SafeConstructor): |
| 620 | 603 | return self.construct_python_object_apply(suffix, node, newobj=True) |
| 621 | 604 | |
| 622 | 605 | Constructor.add_constructor( |
| 623 | | u'tag:yaml.org,2002:python/none', |
| | 606 | 'tag:yaml.org,2002:python/none', |
| 624 | 607 | Constructor.construct_yaml_null) |
| 625 | 608 | |
| 626 | 609 | Constructor.add_constructor( |
| 627 | | u'tag:yaml.org,2002:python/bool', |
| | 610 | 'tag:yaml.org,2002:python/bool', |
| 628 | 611 | Constructor.construct_yaml_bool) |
| 629 | 612 | |
| 630 | 613 | Constructor.add_constructor( |
| 631 | | u'tag:yaml.org,2002:python/str', |
| | 614 | 'tag:yaml.org,2002:python/str', |
| 632 | 615 | Constructor.construct_python_str) |
| 633 | 616 | |
| 634 | 617 | Constructor.add_constructor( |
| 635 | | u'tag:yaml.org,2002:python/unicode', |
| | 618 | 'tag:yaml.org,2002:python/unicode', |
| 636 | 619 | Constructor.construct_python_unicode) |
| 637 | 620 | |
| 638 | 621 | Constructor.add_constructor( |
| 639 | | u'tag:yaml.org,2002:python/int', |
| | 622 | 'tag:yaml.org,2002:python/bytes', |
| | 623 | Constructor.construct_python_bytes) |
| | 624 | |
| | 625 | Constructor.add_constructor( |
| | 626 | 'tag:yaml.org,2002:python/int', |
| 640 | 627 | Constructor.construct_yaml_int) |
| 641 | 628 | |
| 642 | 629 | Constructor.add_constructor( |
| 643 | | u'tag:yaml.org,2002:python/long', |
| | 630 | 'tag:yaml.org,2002:python/long', |
| 644 | 631 | Constructor.construct_python_long) |
| 645 | 632 | |
| 646 | 633 | Constructor.add_constructor( |
| 647 | | u'tag:yaml.org,2002:python/float', |
| | 634 | 'tag:yaml.org,2002:python/float', |
| 648 | 635 | Constructor.construct_yaml_float) |
| 649 | 636 | |
| 650 | 637 | Constructor.add_constructor( |
| 651 | | u'tag:yaml.org,2002:python/complex', |
| | 638 | 'tag:yaml.org,2002:python/complex', |
| 652 | 639 | Constructor.construct_python_complex) |
| 653 | 640 | |
| 654 | 641 | Constructor.add_constructor( |
| 655 | | u'tag:yaml.org,2002:python/list', |
| | 642 | 'tag:yaml.org,2002:python/list', |
| 656 | 643 | Constructor.construct_yaml_seq) |
| 657 | 644 | |
| 658 | 645 | Constructor.add_constructor( |
| 659 | | u'tag:yaml.org,2002:python/tuple', |
| | 646 | 'tag:yaml.org,2002:python/tuple', |
| 660 | 647 | Constructor.construct_python_tuple) |
| 661 | 648 | |
| 662 | 649 | Constructor.add_constructor( |
| 663 | | u'tag:yaml.org,2002:python/dict', |
| | 650 | 'tag:yaml.org,2002:python/dict', |
| 664 | 651 | Constructor.construct_yaml_map) |
| 665 | 652 | |
| 666 | 653 | Constructor.add_multi_constructor( |
| 667 | | u'tag:yaml.org,2002:python/name:', |
| | 654 | 'tag:yaml.org,2002:python/name:', |
| 668 | 655 | Constructor.construct_python_name) |
| 669 | 656 | |
| 670 | 657 | Constructor.add_multi_constructor( |
| 671 | | u'tag:yaml.org,2002:python/module:', |
| | 658 | 'tag:yaml.org,2002:python/module:', |
| 672 | 659 | Constructor.construct_python_module) |
| 673 | 660 | |
| 674 | 661 | Constructor.add_multi_constructor( |
| 675 | | u'tag:yaml.org,2002:python/object:', |
| | 662 | 'tag:yaml.org,2002:python/object:', |
| 676 | 663 | Constructor.construct_python_object) |
| 677 | 664 | |
| 678 | 665 | Constructor.add_multi_constructor( |
| 679 | | u'tag:yaml.org,2002:python/object/apply:', |
| | 666 | 'tag:yaml.org,2002:python/object/apply:', |
| 680 | 667 | Constructor.construct_python_object_apply) |
| 681 | 668 | |
| 682 | 669 | Constructor.add_multi_constructor( |
| 683 | | u'tag:yaml.org,2002:python/object/new:', |
| | 670 | 'tag:yaml.org,2002:python/object/new:', |
| 684 | 671 | Constructor.construct_python_object_new) |
| 685 | 672 | |
-
diff --git lib/yaml/dumper.py lib/yaml/dumper.py
index 355c1e2..e06364c 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['BaseDumper', 'SafeDumper', 'Dumper'] |
| 3 | 3 | |
| 4 | | from emitter import * |
| 5 | | from serializer import * |
| 6 | | from representer import * |
| 7 | | from resolver import * |
| | 4 | from yaml.emitter import * |
| | 5 | from yaml.serializer import * |
| | 6 | from yaml.representer import * |
| | 7 | from yaml.resolver import * |
| 8 | 8 | |
| 9 | 9 | class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): |
| 10 | 10 | |
-
diff --git lib/yaml/emitter.py lib/yaml/emitter.py
index d9d1bf8..17789e9 100644
|
|
|
|
| 8 | 8 | |
| 9 | 9 | __all__ = ['Emitter', 'EmitterError'] |
| 10 | 10 | |
| 11 | | from error import YAMLError |
| 12 | | from events import * |
| | 11 | from yaml.error import YAMLError |
| | 12 | from yaml.events import * |
| 13 | 13 | |
| 14 | 14 | import re |
| 15 | 15 | |
| 16 | 16 | class EmitterError(YAMLError): |
| 17 | 17 | pass |
| 18 | 18 | |
| 19 | | class ScalarAnalysis(object): |
| | 19 | class ScalarAnalysis: |
| 20 | 20 | def __init__(self, scalar, empty, multiline, |
| 21 | 21 | allow_flow_plain, allow_block_plain, |
| 22 | 22 | allow_single_quoted, allow_double_quoted, |
| … |
… |
class ScalarAnalysis(object): |
| 30 | 30 | self.allow_double_quoted = allow_double_quoted |
| 31 | 31 | self.allow_block = allow_block |
| 32 | 32 | |
| 33 | | class Emitter(object): |
| | 33 | class Emitter: |
| 34 | 34 | |
| 35 | 35 | DEFAULT_TAG_PREFIXES = { |
| 36 | | u'!' : u'!', |
| 37 | | u'tag:yaml.org,2002:' : u'!!', |
| | 36 | '!' : '!', |
| | 37 | 'tag:yaml.org,2002:' : '!!', |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | def __init__(self, stream, canonical=None, indent=None, width=None, |
| … |
… |
class Emitter(object): |
| 87 | 87 | self.best_width = 80 |
| 88 | 88 | if width and width > self.best_indent*2: |
| 89 | 89 | self.best_width = width |
| 90 | | self.best_line_break = u'\n' |
| 91 | | if line_break in [u'\r', u'\n', u'\r\n']: |
| | 90 | self.best_line_break = '\n' |
| | 91 | if line_break in ['\r', '\n', '\r\n']: |
| 92 | 92 | self.best_line_break = line_break |
| 93 | 93 | |
| 94 | 94 | # Tag prefixes. |
| … |
… |
class Emitter(object): |
| 176 | 176 | self.write_version_directive(version_text) |
| 177 | 177 | self.tag_prefixes = self.DEFAULT_TAG_PREFIXES.copy() |
| 178 | 178 | if self.event.tags: |
| 179 | | handles = self.event.tags.keys() |
| 180 | | handles.sort() |
| | 179 | handles = sorted(self.event.tags.keys()) |
| 181 | 180 | for handle in handles: |
| 182 | 181 | prefix = self.event.tags[handle] |
| 183 | 182 | self.tag_prefixes[prefix] = handle |
| … |
… |
class Emitter(object): |
| 189 | 188 | and not self.check_empty_document()) |
| 190 | 189 | if not implicit: |
| 191 | 190 | self.write_indent() |
| 192 | | self.write_indicator(u'---', True) |
| | 191 | self.write_indicator('---', True) |
| 193 | 192 | if self.canonical: |
| 194 | 193 | self.write_indent() |
| 195 | 194 | self.state = self.expect_document_root |
| … |
… |
class Emitter(object): |
| 204 | 203 | if isinstance(self.event, DocumentEndEvent): |
| 205 | 204 | self.write_indent() |
| 206 | 205 | if self.event.explicit: |
| 207 | | self.write_indicator(u'...', True) |
| | 206 | self.write_indicator('...', True) |
| 208 | 207 | self.write_indent() |
| 209 | 208 | self.flush_stream() |
| 210 | 209 | self.state = self.expect_document_start |
| … |
… |
class Emitter(object): |
| 227 | 226 | if isinstance(self.event, AliasEvent): |
| 228 | 227 | self.expect_alias() |
| 229 | 228 | elif isinstance(self.event, (ScalarEvent, CollectionStartEvent)): |
| 230 | | self.process_anchor(u'&') |
| | 229 | self.process_anchor('&') |
| 231 | 230 | self.process_tag() |
| 232 | 231 | if isinstance(self.event, ScalarEvent): |
| 233 | 232 | self.expect_scalar() |
| … |
… |
class Emitter(object): |
| 249 | 248 | def expect_alias(self): |
| 250 | 249 | if self.event.anchor is None: |
| 251 | 250 | raise EmitterError("anchor is not specified for alias") |
| 252 | | self.process_anchor(u'*') |
| | 251 | self.process_anchor('*') |
| 253 | 252 | self.state = self.states.pop() |
| 254 | 253 | |
| 255 | 254 | def expect_scalar(self): |
| … |
… |
class Emitter(object): |
| 261 | 260 | # Flow sequence handlers. |
| 262 | 261 | |
| 263 | 262 | def expect_flow_sequence(self): |
| 264 | | self.write_indicator(u'[', True, whitespace=True) |
| | 263 | self.write_indicator('[', True, whitespace=True) |
| 265 | 264 | self.flow_level += 1 |
| 266 | 265 | self.increase_indent(flow=True) |
| 267 | 266 | self.state = self.expect_first_flow_sequence_item |
| … |
… |
class Emitter(object): |
| 270 | 269 | if isinstance(self.event, SequenceEndEvent): |
| 271 | 270 | self.indent = self.indents.pop() |
| 272 | 271 | self.flow_level -= 1 |
| 273 | | self.write_indicator(u']', False) |
| | 272 | self.write_indicator(']', False) |
| 274 | 273 | self.state = self.states.pop() |
| 275 | 274 | else: |
| 276 | 275 | if self.canonical or self.column > self.best_width: |
| … |
… |
class Emitter(object): |
| 283 | 282 | self.indent = self.indents.pop() |
| 284 | 283 | self.flow_level -= 1 |
| 285 | 284 | if self.canonical: |
| 286 | | self.write_indicator(u',', False) |
| | 285 | self.write_indicator(',', False) |
| 287 | 286 | self.write_indent() |
| 288 | | self.write_indicator(u']', False) |
| | 287 | self.write_indicator(']', False) |
| 289 | 288 | self.state = self.states.pop() |
| 290 | 289 | else: |
| 291 | | self.write_indicator(u',', False) |
| | 290 | self.write_indicator(',', False) |
| 292 | 291 | if self.canonical or self.column > self.best_width: |
| 293 | 292 | self.write_indent() |
| 294 | 293 | self.states.append(self.expect_flow_sequence_item) |
| … |
… |
class Emitter(object): |
| 297 | 296 | # Flow mapping handlers. |
| 298 | 297 | |
| 299 | 298 | def expect_flow_mapping(self): |
| 300 | | self.write_indicator(u'{', True, whitespace=True) |
| | 299 | self.write_indicator('{', True, whitespace=True) |
| 301 | 300 | self.flow_level += 1 |
| 302 | 301 | self.increase_indent(flow=True) |
| 303 | 302 | self.state = self.expect_first_flow_mapping_key |
| … |
… |
class Emitter(object): |
| 306 | 305 | if isinstance(self.event, MappingEndEvent): |
| 307 | 306 | self.indent = self.indents.pop() |
| 308 | 307 | self.flow_level -= 1 |
| 309 | | self.write_indicator(u'}', False) |
| | 308 | self.write_indicator('}', False) |
| 310 | 309 | self.state = self.states.pop() |
| 311 | 310 | else: |
| 312 | 311 | if self.canonical or self.column > self.best_width: |
| … |
… |
class Emitter(object): |
| 315 | 314 | self.states.append(self.expect_flow_mapping_simple_value) |
| 316 | 315 | self.expect_node(mapping=True, simple_key=True) |
| 317 | 316 | else: |
| 318 | | self.write_indicator(u'?', True) |
| | 317 | self.write_indicator('?', True) |
| 319 | 318 | self.states.append(self.expect_flow_mapping_value) |
| 320 | 319 | self.expect_node(mapping=True) |
| 321 | 320 | |
| … |
… |
class Emitter(object): |
| 324 | 323 | self.indent = self.indents.pop() |
| 325 | 324 | self.flow_level -= 1 |
| 326 | 325 | if self.canonical: |
| 327 | | self.write_indicator(u',', False) |
| | 326 | self.write_indicator(',', False) |
| 328 | 327 | self.write_indent() |
| 329 | | self.write_indicator(u'}', False) |
| | 328 | self.write_indicator('}', False) |
| 330 | 329 | self.state = self.states.pop() |
| 331 | 330 | else: |
| 332 | | self.write_indicator(u',', False) |
| | 331 | self.write_indicator(',', False) |
| 333 | 332 | if self.canonical or self.column > self.best_width: |
| 334 | 333 | self.write_indent() |
| 335 | 334 | if not self.canonical and self.check_simple_key(): |
| 336 | 335 | self.states.append(self.expect_flow_mapping_simple_value) |
| 337 | 336 | self.expect_node(mapping=True, simple_key=True) |
| 338 | 337 | else: |
| 339 | | self.write_indicator(u'?', True) |
| | 338 | self.write_indicator('?', True) |
| 340 | 339 | self.states.append(self.expect_flow_mapping_value) |
| 341 | 340 | self.expect_node(mapping=True) |
| 342 | 341 | |
| 343 | 342 | def expect_flow_mapping_simple_value(self): |
| 344 | | self.write_indicator(u':', False) |
| | 343 | self.write_indicator(':', False) |
| 345 | 344 | self.states.append(self.expect_flow_mapping_key) |
| 346 | 345 | self.expect_node(mapping=True) |
| 347 | 346 | |
| 348 | 347 | def expect_flow_mapping_value(self): |
| 349 | 348 | if self.canonical or self.column > self.best_width: |
| 350 | 349 | self.write_indent() |
| 351 | | self.write_indicator(u':', True) |
| | 350 | self.write_indicator(':', True) |
| 352 | 351 | self.states.append(self.expect_flow_mapping_key) |
| 353 | 352 | self.expect_node(mapping=True) |
| 354 | 353 | |
| … |
… |
class Emitter(object): |
| 368 | 367 | self.state = self.states.pop() |
| 369 | 368 | else: |
| 370 | 369 | self.write_indent() |
| 371 | | self.write_indicator(u'-', True, indention=True) |
| | 370 | self.write_indicator('-', True, indention=True) |
| 372 | 371 | self.states.append(self.expect_block_sequence_item) |
| 373 | 372 | self.expect_node(sequence=True) |
| 374 | 373 | |
| … |
… |
class Emitter(object): |
| 391 | 390 | self.states.append(self.expect_block_mapping_simple_value) |
| 392 | 391 | self.expect_node(mapping=True, simple_key=True) |
| 393 | 392 | else: |
| 394 | | self.write_indicator(u'?', True, indention=True) |
| | 393 | self.write_indicator('?', True, indention=True) |
| 395 | 394 | self.states.append(self.expect_block_mapping_value) |
| 396 | 395 | self.expect_node(mapping=True) |
| 397 | 396 | |
| 398 | 397 | def expect_block_mapping_simple_value(self): |
| 399 | | self.write_indicator(u':', False) |
| | 398 | self.write_indicator(':', False) |
| 400 | 399 | self.states.append(self.expect_block_mapping_key) |
| 401 | 400 | self.expect_node(mapping=True) |
| 402 | 401 | |
| 403 | 402 | def expect_block_mapping_value(self): |
| 404 | 403 | self.write_indent() |
| 405 | | self.write_indicator(u':', True, indention=True) |
| | 404 | self.write_indicator(':', True, indention=True) |
| 406 | 405 | self.states.append(self.expect_block_mapping_key) |
| 407 | 406 | self.expect_node(mapping=True) |
| 408 | 407 | |
| … |
… |
class Emitter(object): |
| 421 | 420 | return False |
| 422 | 421 | event = self.events[0] |
| 423 | 422 | return (isinstance(event, ScalarEvent) and event.anchor is None |
| 424 | | and event.tag is None and event.implicit and event.value == u'') |
| | 423 | and event.tag is None and event.implicit and event.value == '') |
| 425 | 424 | |
| 426 | 425 | def check_simple_key(self): |
| 427 | 426 | length = 0 |
| … |
… |
class Emitter(object): |
| 466 | 465 | self.prepared_tag = None |
| 467 | 466 | return |
| 468 | 467 | if self.event.implicit[0] and tag is None: |
| 469 | | tag = u'!' |
| | 468 | tag = '!' |
| 470 | 469 | self.prepared_tag = None |
| 471 | 470 | else: |
| 472 | 471 | if (not self.canonical or tag is None) and self.event.implicit: |
| … |
… |
class Emitter(object): |
| 529 | 528 | major, minor = version |
| 530 | 529 | if major != 1: |
| 531 | 530 | raise EmitterError("unsupported YAML version: %d.%d" % (major, minor)) |
| 532 | | return u'%d.%d' % (major, minor) |
| | 531 | return '%d.%d' % (major, minor) |
| 533 | 532 | |
| 534 | 533 | def prepare_tag_handle(self, handle): |
| 535 | 534 | if not handle: |
| 536 | 535 | raise EmitterError("tag handle must not be empty") |
| 537 | | if handle[0] != u'!' or handle[-1] != u'!': |
| | 536 | if handle[0] != '!' or handle[-1] != '!': |
| 538 | 537 | raise EmitterError("tag handle must start and end with '!': %r" |
| 539 | 538 | % (handle.encode('utf-8'))) |
| 540 | 539 | for ch in handle[1:-1]: |
| 541 | | if not (u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 542 | | or ch in u'-_'): |
| | 540 | if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 541 | or ch in '-_'): |
| 543 | 542 | raise EmitterError("invalid character %r in the tag handle: %r" |
| 544 | 543 | % (ch.encode('utf-8'), handle.encode('utf-8'))) |
| 545 | 544 | return handle |
| … |
… |
class Emitter(object): |
| 549 | 548 | raise EmitterError("tag prefix must not be empty") |
| 550 | 549 | chunks = [] |
| 551 | 550 | start = end = 0 |
| 552 | | if prefix[0] == u'!': |
| | 551 | if prefix[0] == '!': |
| 553 | 552 | end = 1 |
| 554 | 553 | while end < len(prefix): |
| 555 | 554 | ch = prefix[end] |
| 556 | | if u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 557 | | or ch in u'-;/?!:@&=+$,_.~*\'()[]': |
| | 555 | if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 556 | or ch in '-;/?!:@&=+$,_.~*\'()[]': |
| 558 | 557 | end += 1 |
| 559 | 558 | else: |
| 560 | 559 | if start < end: |
| … |
… |
class Emitter(object): |
| 562 | 561 | start = end = end+1 |
| 563 | 562 | data = ch.encode('utf-8') |
| 564 | 563 | for ch in data: |
| 565 | | chunks.append(u'%%%02X' % ord(ch)) |
| | 564 | chunks.append('%%%02X' % ord(ch)) |
| 566 | 565 | if start < end: |
| 567 | 566 | chunks.append(prefix[start:end]) |
| 568 | | return u''.join(chunks) |
| | 567 | return ''.join(chunks) |
| 569 | 568 | |
| 570 | 569 | def prepare_tag(self, tag): |
| 571 | 570 | if not tag: |
| 572 | 571 | raise EmitterError("tag must not be empty") |
| 573 | | if tag == u'!': |
| | 572 | if tag == '!': |
| 574 | 573 | return tag |
| 575 | 574 | handle = None |
| 576 | 575 | suffix = tag |
| 577 | 576 | for prefix in self.tag_prefixes: |
| 578 | 577 | if tag.startswith(prefix) \ |
| 579 | | and (prefix == u'!' or len(prefix) < len(tag)): |
| | 578 | and (prefix == '!' or len(prefix) < len(tag)): |
| 580 | 579 | handle = self.tag_prefixes[prefix] |
| 581 | 580 | suffix = tag[len(prefix):] |
| 582 | 581 | chunks = [] |
| 583 | 582 | start = end = 0 |
| 584 | 583 | while end < len(suffix): |
| 585 | 584 | ch = suffix[end] |
| 586 | | if u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 587 | | or ch in u'-;/?:@&=+$,_.~*\'()[]' \ |
| 588 | | or (ch == u'!' and handle != u'!'): |
| | 585 | if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 586 | or ch in '-;/?:@&=+$,_.~*\'()[]' \ |
| | 587 | or (ch == '!' and handle != '!'): |
| 589 | 588 | end += 1 |
| 590 | 589 | else: |
| 591 | 590 | if start < end: |
| … |
… |
class Emitter(object): |
| 593 | 592 | start = end = end+1 |
| 594 | 593 | data = ch.encode('utf-8') |
| 595 | 594 | for ch in data: |
| 596 | | chunks.append(u'%%%02X' % ord(ch)) |
| | 595 | chunks.append('%%%02X' % ord(ch)) |
| 597 | 596 | if start < end: |
| 598 | 597 | chunks.append(suffix[start:end]) |
| 599 | | suffix_text = u''.join(chunks) |
| | 598 | suffix_text = ''.join(chunks) |
| 600 | 599 | if handle: |
| 601 | | return u'%s%s' % (handle, suffix_text) |
| | 600 | return '%s%s' % (handle, suffix_text) |
| 602 | 601 | else: |
| 603 | | return u'!<%s>' % suffix_text |
| | 602 | return '!<%s>' % suffix_text |
| 604 | 603 | |
| 605 | 604 | def prepare_anchor(self, anchor): |
| 606 | 605 | if not anchor: |
| 607 | 606 | raise EmitterError("anchor must not be empty") |
| 608 | 607 | for ch in anchor: |
| 609 | | if not (u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 610 | | or ch in u'-_'): |
| | 608 | if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 609 | or ch in '-_'): |
| 611 | 610 | raise EmitterError("invalid character %r in the anchor: %r" |
| 612 | 611 | % (ch.encode('utf-8'), anchor.encode('utf-8'))) |
| 613 | 612 | return anchor |
| … |
… |
class Emitter(object): |
| 638 | 637 | mixed_breaks_spaces = False # anything else |
| 639 | 638 | |
| 640 | 639 | # Check document indicators. |
| 641 | | if scalar.startswith(u'---') or scalar.startswith(u'...'): |
| | 640 | if scalar.startswith('---') or scalar.startswith('...'): |
| 642 | 641 | block_indicators = True |
| 643 | 642 | flow_indicators = True |
| 644 | 643 | |
| … |
… |
class Emitter(object): |
| 647 | 646 | |
| 648 | 647 | # Last character or followed by a whitespace. |
| 649 | 648 | followed_by_space = (len(scalar) == 1 or |
| 650 | | scalar[1] in u'\0 \t\r\n\x85\u2028\u2029') |
| | 649 | scalar[1] in '\0 \t\r\n\x85\u2028\u2029') |
| 651 | 650 | |
| 652 | 651 | # The current series of whitespaces contain plain spaces. |
| 653 | 652 | spaces = False |
| … |
… |
class Emitter(object): |
| 671 | 670 | |
| 672 | 671 | if index == 0: |
| 673 | 672 | # Leading indicators are special characters. |
| 674 | | if ch in u'#,[]{}&*!|>\'\"%@`': |
| | 673 | if ch in '#,[]{}&*!|>\'\"%@`': |
| 675 | 674 | flow_indicators = True |
| 676 | 675 | block_indicators = True |
| 677 | | if ch in u'?:': |
| | 676 | if ch in '?:': |
| 678 | 677 | flow_indicators = True |
| 679 | 678 | if followed_by_space: |
| 680 | 679 | block_indicators = True |
| 681 | | if ch == u'-' and followed_by_space: |
| | 680 | if ch == '-' and followed_by_space: |
| 682 | 681 | flow_indicators = True |
| 683 | 682 | block_indicators = True |
| 684 | 683 | else: |
| 685 | 684 | # Some indicators cannot appear within a scalar as well. |
| 686 | | if ch in u',?[]{}': |
| | 685 | if ch in ',?[]{}': |
| 687 | 686 | flow_indicators = True |
| 688 | | if ch == u':': |
| | 687 | if ch == ':': |
| 689 | 688 | flow_indicators = True |
| 690 | 689 | if followed_by_space: |
| 691 | 690 | block_indicators = True |
| 692 | | if ch == u'#' and preceeded_by_space: |
| | 691 | if ch == '#' and preceeded_by_space: |
| 693 | 692 | flow_indicators = True |
| 694 | 693 | block_indicators = True |
| 695 | 694 | |
| 696 | 695 | # Check for line breaks, special, and unicode characters. |
| 697 | 696 | |
| 698 | | if ch in u'\n\x85\u2028\u2029': |
| | 697 | if ch in '\n\x85\u2028\u2029': |
| 699 | 698 | line_breaks = True |
| 700 | | if not (ch == u'\n' or u'\x20' <= ch <= u'\x7E'): |
| 701 | | if (ch == u'\x85' or u'\xA0' <= ch <= u'\uD7FF' |
| 702 | | or u'\uE000' <= ch <= u'\uFFFD') and ch != u'\uFEFF': |
| | 699 | if not (ch == '\n' or '\x20' <= ch <= '\x7E'): |
| | 700 | if (ch == '\x85' or '\xA0' <= ch <= '\uD7FF' |
| | 701 | or '\uE000' <= ch <= '\uFFFD') and ch != '\uFEFF': |
| 703 | 702 | unicode_characters = True |
| 704 | 703 | if not self.allow_unicode: |
| 705 | 704 | special_characters = True |
| … |
… |
class Emitter(object): |
| 709 | 708 | # Spaces, line breaks, and how they are mixed. State machine. |
| 710 | 709 | |
| 711 | 710 | # Start or continue series of whitespaces. |
| 712 | | if ch in u' \n\x85\u2028\u2029': |
| | 711 | if ch in ' \n\x85\u2028\u2029': |
| 713 | 712 | if spaces and breaks: |
| 714 | | if ch != u' ': # break+ (space+ break+) => mixed |
| | 713 | if ch != ' ': # break+ (space+ break+) => mixed |
| 715 | 714 | mixed = True |
| 716 | 715 | elif spaces: |
| 717 | | if ch != u' ': # (space+ break+) => mixed |
| | 716 | if ch != ' ': # (space+ break+) => mixed |
| 718 | 717 | breaks = True |
| 719 | 718 | mixed = True |
| 720 | 719 | elif breaks: |
| 721 | | if ch == u' ': # break+ space+ |
| | 720 | if ch == ' ': # break+ space+ |
| 722 | 721 | spaces = True |
| 723 | 722 | else: |
| 724 | 723 | leading = (index == 0) |
| 725 | | if ch == u' ': # space+ |
| | 724 | if ch == ' ': # space+ |
| 726 | 725 | spaces = True |
| 727 | 726 | else: # break+ |
| 728 | 727 | breaks = True |
| … |
… |
class Emitter(object): |
| 763 | 762 | |
| 764 | 763 | # Prepare for the next character. |
| 765 | 764 | index += 1 |
| 766 | | preceeded_by_space = (ch in u'\0 \t\r\n\x85\u2028\u2029') |
| | 765 | preceeded_by_space = (ch in '\0 \t\r\n\x85\u2028\u2029') |
| 767 | 766 | followed_by_space = (index+1 >= len(scalar) or |
| 768 | | scalar[index+1] in u'\0 \t\r\n\x85\u2028\u2029') |
| | 767 | scalar[index+1] in '\0 \t\r\n\x85\u2028\u2029') |
| 769 | 768 | |
| 770 | 769 | # Let's decide what styles are allowed. |
| 771 | 770 | allow_flow_plain = True |
| … |
… |
class Emitter(object): |
| 824 | 823 | def write_stream_start(self): |
| 825 | 824 | # Write BOM if needed. |
| 826 | 825 | if self.encoding and self.encoding.startswith('utf-16'): |
| 827 | | self.stream.write(u'\xFF\xFE'.encode(self.encoding)) |
| | 826 | self.stream.write('\xFF\xFE'.encode(self.encoding)) |
| 828 | 827 | |
| 829 | 828 | def write_stream_end(self): |
| 830 | 829 | self.flush_stream() |
| … |
… |
class Emitter(object): |
| 834 | 833 | if self.whitespace or not need_whitespace: |
| 835 | 834 | data = indicator |
| 836 | 835 | else: |
| 837 | | data = u' '+indicator |
| | 836 | data = ' '+indicator |
| 838 | 837 | self.whitespace = whitespace |
| 839 | 838 | self.indention = self.indention and indention |
| 840 | 839 | self.column += len(data) |
| 841 | | if self.encoding: |
| 842 | | data = data.encode(self.encoding) |
| 843 | 840 | self.stream.write(data) |
| 844 | 841 | |
| 845 | 842 | def write_indent(self): |
| … |
… |
class Emitter(object): |
| 849 | 846 | self.write_line_break() |
| 850 | 847 | if self.column < indent: |
| 851 | 848 | self.whitespace = True |
| 852 | | data = u' '*(indent-self.column) |
| | 849 | data = ' '*(indent-self.column) |
| 853 | 850 | self.column = indent |
| 854 | | if self.encoding: |
| 855 | | data = data.encode(self.encoding) |
| 856 | 851 | self.stream.write(data) |
| 857 | 852 | |
| 858 | 853 | def write_line_break(self, data=None): |
| … |
… |
class Emitter(object): |
| 862 | 857 | self.indention = True |
| 863 | 858 | self.line += 1 |
| 864 | 859 | self.column = 0 |
| 865 | | if self.encoding: |
| 866 | | data = data.encode(self.encoding) |
| 867 | 860 | self.stream.write(data) |
| 868 | 861 | |
| 869 | 862 | def write_version_directive(self, version_text): |
| 870 | | data = u'%%YAML %s' % version_text |
| 871 | | if self.encoding: |
| 872 | | data = data.encode(self.encoding) |
| | 863 | data = '%%YAML %s' % version_text |
| 873 | 864 | self.stream.write(data) |
| 874 | 865 | self.write_line_break() |
| 875 | 866 | |
| 876 | 867 | def write_tag_directive(self, handle_text, prefix_text): |
| 877 | | data = u'%%TAG %s %s' % (handle_text, prefix_text) |
| 878 | | if self.encoding: |
| 879 | | data = data.encode(self.encoding) |
| | 868 | data = '%%TAG %s %s' % (handle_text, prefix_text) |
| 880 | 869 | self.stream.write(data) |
| 881 | 870 | self.write_line_break() |
| 882 | 871 | |
| 883 | 872 | # Scalar streams. |
| 884 | 873 | |
| 885 | 874 | def write_single_quoted(self, text, split=True): |
| 886 | | self.write_indicator(u'\'', True) |
| | 875 | self.write_indicator('\'', True) |
| 887 | 876 | spaces = False |
| 888 | 877 | breaks = False |
| 889 | 878 | start = end = 0 |
| … |
… |
class Emitter(object): |
| 892 | 881 | if end < len(text): |
| 893 | 882 | ch = text[end] |
| 894 | 883 | if spaces: |
| 895 | | if ch is None or ch != u' ': |
| | 884 | if ch is None or ch != ' ': |
| 896 | 885 | if start+1 == end and self.column > self.best_width and split \ |
| 897 | 886 | and start != 0 and end != len(text): |
| 898 | 887 | self.write_indent() |
| 899 | 888 | else: |
| 900 | 889 | data = text[start:end] |
| 901 | 890 | self.column += len(data) |
| 902 | | if self.encoding: |
| 903 | | data = data.encode(self.encoding) |
| 904 | 891 | self.stream.write(data) |
| 905 | 892 | start = end |
| 906 | 893 | elif breaks: |
| 907 | | if ch is None or ch not in u'\n\x85\u2028\u2029': |
| 908 | | if text[start] == u'\n': |
| | 894 | if ch is None or ch not in '\n\x85\u2028\u2029': |
| | 895 | if text[start] == '\n': |
| 909 | 896 | self.write_line_break() |
| 910 | 897 | for br in text[start:end]: |
| 911 | | if br == u'\n': |
| | 898 | if br == '\n': |
| 912 | 899 | self.write_line_break() |
| 913 | 900 | else: |
| 914 | 901 | self.write_line_break(br) |
| 915 | 902 | self.write_indent() |
| 916 | 903 | start = end |
| 917 | 904 | else: |
| 918 | | if ch is None or ch in u' \n\x85\u2028\u2029' or ch == u'\'': |
| | 905 | if ch is None or ch in ' \n\x85\u2028\u2029' or ch == '\'': |
| 919 | 906 | if start < end: |
| 920 | 907 | data = text[start:end] |
| 921 | 908 | self.column += len(data) |
| 922 | | if self.encoding: |
| 923 | | data = data.encode(self.encoding) |
| 924 | 909 | self.stream.write(data) |
| 925 | 910 | start = end |
| 926 | | if ch == u'\'': |
| 927 | | data = u'\'\'' |
| | 911 | if ch == '\'': |
| | 912 | data = '\'\'' |
| 928 | 913 | self.column += 2 |
| 929 | | if self.encoding: |
| 930 | | data = data.encode(self.encoding) |
| 931 | 914 | self.stream.write(data) |
| 932 | 915 | start = end + 1 |
| 933 | 916 | if ch is not None: |
| 934 | | spaces = (ch == u' ') |
| 935 | | breaks = (ch in u'\n\x85\u2028\u2029') |
| | 917 | spaces = (ch == ' ') |
| | 918 | breaks = (ch in '\n\x85\u2028\u2029') |
| 936 | 919 | end += 1 |
| 937 | | self.write_indicator(u'\'', False) |
| | 920 | self.write_indicator('\'', False) |
| 938 | 921 | |
| 939 | 922 | ESCAPE_REPLACEMENTS = { |
| 940 | | u'\0': u'0', |
| 941 | | u'\x07': u'a', |
| 942 | | u'\x08': u'b', |
| 943 | | u'\x09': u't', |
| 944 | | u'\x0A': u'n', |
| 945 | | u'\x0B': u'v', |
| 946 | | u'\x0C': u'f', |
| 947 | | u'\x0D': u'r', |
| 948 | | u'\x1B': u'e', |
| 949 | | u'\"': u'\"', |
| 950 | | u'\\': u'\\', |
| 951 | | u'\x85': u'N', |
| 952 | | u'\xA0': u'_', |
| 953 | | u'\u2028': u'L', |
| 954 | | u'\u2029': u'P', |
| | 923 | '\0': '0', |
| | 924 | '\x07': 'a', |
| | 925 | '\x08': 'b', |
| | 926 | '\x09': 't', |
| | 927 | '\x0A': 'n', |
| | 928 | '\x0B': 'v', |
| | 929 | '\x0C': 'f', |
| | 930 | '\x0D': 'r', |
| | 931 | '\x1B': 'e', |
| | 932 | '\"': '\"', |
| | 933 | '\\': '\\', |
| | 934 | '\x85': 'N', |
| | 935 | '\xA0': '_', |
| | 936 | '\u2028': 'L', |
| | 937 | '\u2029': 'P', |
| 955 | 938 | } |
| 956 | 939 | |
| 957 | 940 | def write_double_quoted(self, text, split=True): |
| 958 | | self.write_indicator(u'"', True) |
| | 941 | self.write_indicator('"', True) |
| 959 | 942 | start = end = 0 |
| 960 | 943 | while end <= len(text): |
| 961 | 944 | ch = None |
| 962 | 945 | if end < len(text): |
| 963 | 946 | ch = text[end] |
| 964 | | if ch is None or ch in u'"\\\x85\u2028\u2029\uFEFF' \ |
| 965 | | or not (u'\x20' <= ch <= u'\x7E' |
| | 947 | if ch is None or ch in '"\\\x85\u2028\u2029\uFEFF' \ |
| | 948 | or not ('\x20' <= ch <= '\x7E' |
| 966 | 949 | or (self.allow_unicode |
| 967 | | and (u'\xA0' <= ch <= u'\uD7FF' |
| 968 | | or u'\uE000' <= ch <= u'\uFFFD'))): |
| | 950 | and ('\xA0' <= ch <= '\uD7FF' |
| | 951 | or '\uE000' <= ch <= '\uFFFD'))): |
| 969 | 952 | if start < end: |
| 970 | 953 | data = text[start:end] |
| 971 | 954 | self.column += len(data) |
| 972 | | if self.encoding: |
| 973 | | data = data.encode(self.encoding) |
| 974 | 955 | self.stream.write(data) |
| 975 | 956 | start = end |
| 976 | 957 | if ch is not None: |
| 977 | 958 | if ch in self.ESCAPE_REPLACEMENTS: |
| 978 | | data = u'\\'+self.ESCAPE_REPLACEMENTS[ch] |
| 979 | | elif ch <= u'\xFF': |
| 980 | | data = u'\\x%02X' % ord(ch) |
| 981 | | elif ch <= u'\uFFFF': |
| 982 | | data = u'\\u%04X' % ord(ch) |
| | 959 | data = '\\'+self.ESCAPE_REPLACEMENTS[ch] |
| | 960 | elif ch <= '\xFF': |
| | 961 | data = '\\x%02X' % ord(ch) |
| | 962 | elif ch <= '\uFFFF': |
| | 963 | data = '\\u%04X' % ord(ch) |
| 983 | 964 | else: |
| 984 | | data = u'\\U%08X' % ord(ch) |
| | 965 | data = '\\U%08X' % ord(ch) |
| 985 | 966 | self.column += len(data) |
| 986 | | if self.encoding: |
| 987 | | data = data.encode(self.encoding) |
| 988 | 967 | self.stream.write(data) |
| 989 | 968 | start = end+1 |
| 990 | | if 0 < end < len(text)-1 and (ch == u' ' or start >= end) \ |
| | 969 | if 0 < end < len(text)-1 and (ch == ' ' or start >= end) \ |
| 991 | 970 | and self.column+(end-start) > self.best_width and split: |
| 992 | | data = text[start:end]+u'\\' |
| | 971 | data = text[start:end]+'\\' |
| 993 | 972 | if start < end: |
| 994 | 973 | start = end |
| 995 | 974 | self.column += len(data) |
| 996 | | if self.encoding: |
| 997 | | data = data.encode(self.encoding) |
| 998 | 975 | self.stream.write(data) |
| 999 | 976 | self.write_indent() |
| 1000 | 977 | self.whitespace = False |
| 1001 | 978 | self.indention = False |
| 1002 | | if text[start] == u' ': |
| 1003 | | data = u'\\' |
| | 979 | if text[start] == ' ': |
| | 980 | data = '\\' |
| 1004 | 981 | self.column += len(data) |
| 1005 | | if self.encoding: |
| 1006 | | data = data.encode(self.encoding) |
| 1007 | 982 | self.stream.write(data) |
| 1008 | 983 | end += 1 |
| 1009 | | self.write_indicator(u'"', False) |
| | 984 | self.write_indicator('"', False) |
| 1010 | 985 | |
| 1011 | 986 | def determine_chomp(self, text): |
| 1012 | 987 | tail = text[-2:] |
| 1013 | 988 | while len(tail) < 2: |
| 1014 | | tail = u' '+tail |
| 1015 | | if tail[-1] in u'\n\x85\u2028\u2029': |
| 1016 | | if tail[-2] in u'\n\x85\u2028\u2029': |
| 1017 | | return u'+' |
| | 989 | tail = ' '+tail |
| | 990 | if tail[-1] in '\n\x85\u2028\u2029': |
| | 991 | if tail[-2] in '\n\x85\u2028\u2029': |
| | 992 | return '+' |
| 1018 | 993 | else: |
| 1019 | | return u'' |
| | 994 | return '' |
| 1020 | 995 | else: |
| 1021 | | return u'-' |
| | 996 | return '-' |
| 1022 | 997 | |
| 1023 | 998 | def write_folded(self, text): |
| 1024 | 999 | chomp = self.determine_chomp(text) |
| 1025 | | self.write_indicator(u'>'+chomp, True) |
| | 1000 | self.write_indicator('>'+chomp, True) |
| 1026 | 1001 | self.write_indent() |
| 1027 | 1002 | leading_space = False |
| 1028 | 1003 | spaces = False |
| … |
… |
class Emitter(object): |
| 1033 | 1008 | if end < len(text): |
| 1034 | 1009 | ch = text[end] |
| 1035 | 1010 | if breaks: |
| 1036 | | if ch is None or ch not in u'\n\x85\u2028\u2029': |
| 1037 | | if not leading_space and ch is not None and ch != u' ' \ |
| 1038 | | and text[start] == u'\n': |
| | 1011 | if ch is None or ch not in '\n\x85\u2028\u2029': |
| | 1012 | if not leading_space and ch is not None and ch != ' ' \ |
| | 1013 | and text[start] == '\n': |
| 1039 | 1014 | self.write_line_break() |
| 1040 | | leading_space = (ch == u' ') |
| | 1015 | leading_space = (ch == ' ') |
| 1041 | 1016 | for br in text[start:end]: |
| 1042 | | if br == u'\n': |
| | 1017 | if br == '\n': |
| 1043 | 1018 | self.write_line_break() |
| 1044 | 1019 | else: |
| 1045 | 1020 | self.write_line_break(br) |
| … |
… |
class Emitter(object): |
| 1047 | 1022 | self.write_indent() |
| 1048 | 1023 | start = end |
| 1049 | 1024 | elif spaces: |
| 1050 | | if ch != u' ': |
| | 1025 | if ch != ' ': |
| 1051 | 1026 | if start+1 == end and self.column > self.best_width: |
| 1052 | 1027 | self.write_indent() |
| 1053 | 1028 | else: |
| 1054 | 1029 | data = text[start:end] |
| 1055 | 1030 | self.column += len(data) |
| 1056 | | if self.encoding: |
| 1057 | | data = data.encode(self.encoding) |
| 1058 | 1031 | self.stream.write(data) |
| 1059 | 1032 | start = end |
| 1060 | 1033 | else: |
| 1061 | | if ch is None or ch in u' \n\x85\u2028\u2029': |
| | 1034 | if ch is None or ch in ' \n\x85\u2028\u2029': |
| 1062 | 1035 | data = text[start:end] |
| 1063 | | if self.encoding: |
| 1064 | | data = data.encode(self.encoding) |
| 1065 | 1036 | self.stream.write(data) |
| 1066 | 1037 | if ch is None: |
| 1067 | 1038 | self.write_line_break() |
| 1068 | 1039 | start = end |
| 1069 | 1040 | if ch is not None: |
| 1070 | | breaks = (ch in u'\n\x85\u2028\u2029') |
| 1071 | | spaces = (ch == u' ') |
| | 1041 | breaks = (ch in '\n\x85\u2028\u2029') |
| | 1042 | spaces = (ch == ' ') |
| 1072 | 1043 | end += 1 |
| 1073 | 1044 | |
| 1074 | 1045 | def write_literal(self, text): |
| 1075 | 1046 | chomp = self.determine_chomp(text) |
| 1076 | | self.write_indicator(u'|'+chomp, True) |
| | 1047 | self.write_indicator('|'+chomp, True) |
| 1077 | 1048 | self.write_indent() |
| 1078 | 1049 | breaks = False |
| 1079 | 1050 | start = end = 0 |
| … |
… |
class Emitter(object): |
| 1082 | 1053 | if end < len(text): |
| 1083 | 1054 | ch = text[end] |
| 1084 | 1055 | if breaks: |
| 1085 | | if ch is None or ch not in u'\n\x85\u2028\u2029': |
| | 1056 | if ch is None or ch not in '\n\x85\u2028\u2029': |
| 1086 | 1057 | for br in text[start:end]: |
| 1087 | | if br == u'\n': |
| | 1058 | if br == '\n': |
| 1088 | 1059 | self.write_line_break() |
| 1089 | 1060 | else: |
| 1090 | 1061 | self.write_line_break(br) |
| … |
… |
class Emitter(object): |
| 1092 | 1063 | self.write_indent() |
| 1093 | 1064 | start = end |
| 1094 | 1065 | else: |
| 1095 | | if ch is None or ch in u'\n\x85\u2028\u2029': |
| | 1066 | if ch is None or ch in '\n\x85\u2028\u2029': |
| 1096 | 1067 | data = text[start:end] |
| 1097 | | if self.encoding: |
| 1098 | | data = data.encode(self.encoding) |
| 1099 | 1068 | self.stream.write(data) |
| 1100 | 1069 | if ch is None: |
| 1101 | 1070 | self.write_line_break() |
| 1102 | 1071 | start = end |
| 1103 | 1072 | if ch is not None: |
| 1104 | | breaks = (ch in u'\n\x85\u2028\u2029') |
| | 1073 | breaks = (ch in '\n\x85\u2028\u2029') |
| 1105 | 1074 | end += 1 |
| 1106 | 1075 | |
| 1107 | 1076 | def write_plain(self, text, split=True): |
| 1108 | 1077 | if not text: |
| 1109 | 1078 | return |
| 1110 | 1079 | if not self.whitespace: |
| 1111 | | data = u' ' |
| | 1080 | data = ' ' |
| 1112 | 1081 | self.column += len(data) |
| 1113 | | if self.encoding: |
| 1114 | | data = data.encode(self.encoding) |
| 1115 | 1082 | self.stream.write(data) |
| 1116 | 1083 | self.writespace = False |
| 1117 | 1084 | self.indention = False |
| … |
… |
class Emitter(object): |
| 1123 | 1090 | if end < len(text): |
| 1124 | 1091 | ch = text[end] |
| 1125 | 1092 | if spaces: |
| 1126 | | if ch != u' ': |
| | 1093 | if ch != ' ': |
| 1127 | 1094 | if start+1 == end and self.column > self.best_width and split: |
| 1128 | 1095 | self.write_indent() |
| 1129 | 1096 | self.writespace = False |
| … |
… |
class Emitter(object): |
| 1131 | 1098 | else: |
| 1132 | 1099 | data = text[start:end] |
| 1133 | 1100 | self.column += len(data) |
| 1134 | | if self.encoding: |
| 1135 | | data = data.encode(self.encoding) |
| 1136 | 1101 | self.stream.write(data) |
| 1137 | 1102 | start = end |
| 1138 | 1103 | elif breaks: |
| 1139 | | if ch not in u'\n\x85\u2028\u2029': |
| 1140 | | if text[start] == u'\n': |
| | 1104 | if ch not in '\n\x85\u2028\u2029': |
| | 1105 | if text[start] == '\n': |
| 1141 | 1106 | self.write_line_break() |
| 1142 | 1107 | for br in text[start:end]: |
| 1143 | | if br == u'\n': |
| | 1108 | if br == '\n': |
| 1144 | 1109 | self.write_line_break() |
| 1145 | 1110 | else: |
| 1146 | 1111 | self.write_line_break(br) |
| … |
… |
class Emitter(object): |
| 1149 | 1114 | self.indention = False |
| 1150 | 1115 | start = end |
| 1151 | 1116 | else: |
| 1152 | | if ch is None or ch in u' \n\x85\u2028\u2029': |
| | 1117 | if ch is None or ch in ' \n\x85\u2028\u2029': |
| 1153 | 1118 | data = text[start:end] |
| 1154 | 1119 | self.column += len(data) |
| 1155 | | if self.encoding: |
| 1156 | | data = data.encode(self.encoding) |
| 1157 | 1120 | self.stream.write(data) |
| 1158 | 1121 | start = end |
| 1159 | 1122 | if ch is not None: |
| 1160 | | spaces = (ch == u' ') |
| 1161 | | breaks = (ch in u'\n\x85\u2028\u2029') |
| | 1123 | spaces = (ch == ' ') |
| | 1124 | breaks = (ch in '\n\x85\u2028\u2029') |
| 1162 | 1125 | end += 1 |
| 1163 | 1126 | |
-
diff --git lib/yaml/error.py lib/yaml/error.py
index 577686d..b796b4d 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['Mark', 'YAMLError', 'MarkedYAMLError'] |
| 3 | 3 | |
| 4 | | class Mark(object): |
| | 4 | class Mark: |
| 5 | 5 | |
| 6 | 6 | def __init__(self, name, index, line, column, buffer, pointer): |
| 7 | 7 | self.name = name |
| … |
… |
class Mark(object): |
| 16 | 16 | return None |
| 17 | 17 | head = '' |
| 18 | 18 | start = self.pointer |
| 19 | | while start > 0 and self.buffer[start-1] not in u'\0\r\n\x85\u2028\u2029': |
| | 19 | while start > 0 and self.buffer[start-1] not in '\0\r\n\x85\u2028\u2029': |
| 20 | 20 | start -= 1 |
| 21 | 21 | if self.pointer-start > max_length/2-1: |
| 22 | 22 | head = ' ... ' |
| … |
… |
class Mark(object): |
| 24 | 24 | break |
| 25 | 25 | tail = '' |
| 26 | 26 | end = self.pointer |
| 27 | | while end < len(self.buffer) and self.buffer[end] not in u'\0\r\n\x85\u2028\u2029': |
| | 27 | while end < len(self.buffer) and self.buffer[end] not in '\0\r\n\x85\u2028\u2029': |
| 28 | 28 | end += 1 |
| 29 | 29 | if end-self.pointer > max_length/2-1: |
| 30 | 30 | tail = ' ... ' |
| 31 | 31 | end -= 5 |
| 32 | 32 | break |
| 33 | | snippet = self.buffer[start:end].encode('utf-8') |
| | 33 | snippet = self.buffer[start:end] |
| 34 | 34 | return ' '*indent + head + snippet + tail + '\n' \ |
| 35 | 35 | + ' '*(indent+self.pointer-start+len(head)) + '^' |
| 36 | 36 | |
-
diff --git lib/yaml/events.py lib/yaml/events.py
index f79ad38..3f244fa 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | # Abstract classes. |
| 3 | 3 | |
| 4 | | class Event(object): |
| | 4 | class Event: |
| 5 | 5 | def __init__(self, start_mark=None, end_mark=None): |
| 6 | 6 | self.start_mark = start_mark |
| 7 | 7 | self.end_mark = end_mark |
-
diff --git lib/yaml/loader.py lib/yaml/loader.py
index 293ff46..efde149 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['BaseLoader', 'SafeLoader', 'Loader'] |
| 3 | 3 | |
| 4 | | from reader import * |
| 5 | | from scanner import * |
| 6 | | from parser import * |
| 7 | | from composer import * |
| 8 | | from constructor import * |
| 9 | | from resolver import * |
| | 4 | from yaml.reader import * |
| | 5 | from yaml.scanner import * |
| | 6 | from yaml.parser import * |
| | 7 | from yaml.composer import * |
| | 8 | from yaml.constructor import * |
| | 9 | from yaml.resolver import * |
| 10 | 10 | |
| 11 | 11 | class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, BaseResolver): |
| 12 | 12 | |
-
diff --git lib/yaml/nodes.py lib/yaml/nodes.py
index c4f070c..59cb70d 100644
|
|
|
|
| 1 | 1 | |
| 2 | | class Node(object): |
| | 2 | class Node: |
| 3 | 3 | def __init__(self, tag, value, start_mark, end_mark): |
| 4 | 4 | self.tag = tag |
| 5 | 5 | self.value = value |
| … |
… |
class Node(object): |
| 22 | 22 | value = repr(value) |
| 23 | 23 | return '%s(tag=%r, value=%s)' % (self.__class__.__name__, self.tag, value) |
| 24 | 24 | |
| | 25 | def __lt__(self, other): |
| | 26 | if isinstance(other, Node): |
| | 27 | return self.value < other.value |
| | 28 | return super.__lt__(self, other) |
| | 29 | |
| | 30 | def __hash__(self): |
| | 31 | return id(self) |
| | 32 | |
| 25 | 33 | class ScalarNode(Node): |
| 26 | 34 | id = 'scalar' |
| 27 | 35 | def __init__(self, tag, value, |
-
diff --git lib/yaml/parser.py lib/yaml/parser.py
index a46bb9e..51c6dc8 100644
|
|
|
|
| 61 | 61 | |
| 62 | 62 | __all__ = ['Parser', 'ParserError'] |
| 63 | 63 | |
| 64 | | from error import MarkedYAMLError |
| 65 | | from tokens import * |
| 66 | | from events import * |
| 67 | | from scanner import * |
| | 64 | from yaml.error import MarkedYAMLError |
| | 65 | from yaml.tokens import * |
| | 66 | from yaml.events import * |
| | 67 | from yaml.scanner import * |
| 68 | 68 | |
| 69 | 69 | class ParserError(MarkedYAMLError): |
| 70 | 70 | pass |
| 71 | 71 | |
| 72 | | class Parser(object): |
| | 72 | class Parser: |
| 73 | 73 | # Since writing a recursive-descendant parser is a straightforward task, we |
| 74 | 74 | # do not give many comments here. |
| 75 | 75 | # Note that we use Python generators. If you rewrite the parser in another |
| 76 | 76 | # language, you may replace all 'yield'-s with event handler calls. |
| 77 | 77 | |
| 78 | 78 | DEFAULT_TAGS = { |
| 79 | | u'!': u'!', |
| 80 | | u'!!': u'tag:yaml.org,2002:', |
| | 79 | '!': '!', |
| | 80 | '!!': 'tag:yaml.org,2002:', |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | def __init__(self): |
| … |
… |
class Parser(object): |
| 216 | 216 | self.tag_handles = {} |
| 217 | 217 | while self.check_token(DirectiveToken): |
| 218 | 218 | token = self.get_token() |
| 219 | | if token.name == u'YAML': |
| | 219 | if token.name == 'YAML': |
| 220 | 220 | if self.yaml_version is not None: |
| 221 | 221 | raise ParserError(None, None, |
| 222 | 222 | "found duplicate YAML directive", token.start_mark) |
| … |
… |
class Parser(object): |
| 226 | 226 | "found incompatible YAML document (version 1.* is required)", |
| 227 | 227 | token.start_mark) |
| 228 | 228 | self.yaml_version = token.value |
| 229 | | elif token.name == u'TAG': |
| | 229 | elif token.name == 'TAG': |
| 230 | 230 | handle, prefix = token.value |
| 231 | 231 | if handle in self.tag_handles: |
| 232 | 232 | raise ParserError(None, None, |
| … |
… |
class Parser(object): |
| 305 | 305 | tag = self.tag_handles[handle]+suffix |
| 306 | 306 | else: |
| 307 | 307 | tag = suffix |
| 308 | | #if tag == u'!': |
| | 308 | #if tag == '!': |
| 309 | 309 | # raise ParserError("while parsing a node", start_mark, |
| 310 | 310 | # "found non-specific tag '!'", tag_mark, |
| 311 | 311 | # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") |
| 312 | 312 | if start_mark is None: |
| 313 | 313 | start_mark = end_mark = self.peek_token().start_mark |
| 314 | 314 | event = None |
| 315 | | implicit = (tag is None or tag == u'!') |
| | 315 | implicit = (tag is None or tag == '!') |
| 316 | 316 | if indentless_sequence and self.check_token(BlockEntryToken): |
| 317 | 317 | end_mark = self.peek_token().end_mark |
| 318 | 318 | event = SequenceStartEvent(anchor, tag, implicit, |
| … |
… |
class Parser(object): |
| 322 | 322 | if self.check_token(ScalarToken): |
| 323 | 323 | token = self.get_token() |
| 324 | 324 | end_mark = token.end_mark |
| 325 | | if (token.plain and tag is None) or tag == u'!': |
| | 325 | if (token.plain and tag is None) or tag == '!': |
| 326 | 326 | implicit = (True, False) |
| 327 | 327 | elif tag is None: |
| 328 | 328 | implicit = (False, True) |
| … |
… |
class Parser(object): |
| 354 | 354 | elif anchor is not None or tag is not None: |
| 355 | 355 | # Empty scalars are allowed even if a tag or an anchor is |
| 356 | 356 | # specified. |
| 357 | | event = ScalarEvent(anchor, tag, (implicit, False), u'', |
| | 357 | event = ScalarEvent(anchor, tag, (implicit, False), '', |
| 358 | 358 | start_mark, end_mark) |
| 359 | 359 | self.state = self.states.pop() |
| 360 | 360 | else: |
| … |
… |
class Parser(object): |
| 582 | 582 | return self.process_empty_scalar(self.peek_token().start_mark) |
| 583 | 583 | |
| 584 | 584 | def process_empty_scalar(self, mark): |
| 585 | | return ScalarEvent(None, None, (True, False), u'', mark, mark) |
| | 585 | return ScalarEvent(None, None, (True, False), '', mark, mark) |
| 586 | 586 | |
-
diff --git lib/yaml/reader.py lib/yaml/reader.py
index 1d4667c..1998ce2 100644
|
|
|
|
| 17 | 17 | |
| 18 | 18 | __all__ = ['Reader', 'ReaderError'] |
| 19 | 19 | |
| 20 | | from error import YAMLError, Mark |
| 21 | | |
| 22 | | import codecs, re |
| 23 | | |
| 24 | | # Unfortunately, codec functions in Python 2.3 does not support the `finish` |
| 25 | | # arguments, so we have to write our own wrappers. |
| 26 | | |
| 27 | | try: |
| 28 | | codecs.utf_8_decode('', 'strict', False) |
| 29 | | from codecs import utf_8_decode, utf_16_le_decode, utf_16_be_decode |
| 30 | | |
| 31 | | except TypeError: |
| 32 | | |
| 33 | | def utf_16_le_decode(data, errors, finish=False): |
| 34 | | if not finish and len(data) % 2 == 1: |
| 35 | | data = data[:-1] |
| 36 | | return codecs.utf_16_le_decode(data, errors) |
| 37 | | |
| 38 | | def utf_16_be_decode(data, errors, finish=False): |
| 39 | | if not finish and len(data) % 2 == 1: |
| 40 | | data = data[:-1] |
| 41 | | return codecs.utf_16_be_decode(data, errors) |
| 42 | | |
| 43 | | def utf_8_decode(data, errors, finish=False): |
| 44 | | if not finish: |
| 45 | | # We are trying to remove a possible incomplete multibyte character |
| 46 | | # from the suffix of the data. |
| 47 | | # The first byte of a multi-byte sequence is in the range 0xc0 to 0xfd. |
| 48 | | # All further bytes are in the range 0x80 to 0xbf. |
| 49 | | # UTF-8 encoded UCS characters may be up to six bytes long. |
| 50 | | count = 0 |
| 51 | | while count < 5 and count < len(data) \ |
| 52 | | and '\x80' <= data[-count-1] <= '\xBF': |
| 53 | | count -= 1 |
| 54 | | if count < 5 and count < len(data) \ |
| 55 | | and '\xC0' <= data[-count-1] <= '\xFD': |
| 56 | | data = data[:-count-1] |
| 57 | | return codecs.utf_8_decode(data, errors) |
| | 20 | from yaml.error import YAMLError, Mark |
| | 21 | |
| | 22 | import codecs, re, io |
| 58 | 23 | |
| 59 | 24 | class ReaderError(YAMLError): |
| 60 | 25 | |
| … |
… |
class ReaderError(YAMLError): |
| 66 | 31 | self.reason = reason |
| 67 | 32 | |
| 68 | 33 | def __str__(self): |
| 69 | | if isinstance(self.character, str): |
| 70 | | return "'%s' codec can't decode byte #x%02x: %s\n" \ |
| | 34 | if isinstance(self.character, bytes): |
| | 35 | return "'%s' codec can't decode #x%02x: %s\n" \ |
| 71 | 36 | " in \"%s\", position %d" \ |
| 72 | 37 | % (self.encoding, ord(self.character), self.reason, |
| 73 | 38 | self.name, self.position) |
| 74 | 39 | else: |
| 75 | | return "unacceptable character #x%04x: %s\n" \ |
| | 40 | return "unacceptable character %r: %s\n" \ |
| 76 | 41 | " in \"%s\", position %d" \ |
| 77 | | % (ord(self.character), self.reason, |
| | 42 | % (self.character, self.reason, |
| 78 | 43 | self.name, self.position) |
| 79 | 44 | |
| 80 | | class Reader(object): |
| | 45 | class Reader: |
| 81 | 46 | # Reader: |
| 82 | 47 | # - determines the data encoding and converts it to unicode, |
| 83 | 48 | # - checks if characters are in allowed range, |
| … |
… |
class Reader(object): |
| 96 | 61 | self.stream = None |
| 97 | 62 | self.stream_pointer = 0 |
| 98 | 63 | self.eof = True |
| 99 | | self.buffer = u'' |
| | 64 | self.buffer = '' |
| 100 | 65 | self.pointer = 0 |
| 101 | 66 | self.raw_buffer = None |
| 102 | 67 | self.raw_decode = None |
| … |
… |
class Reader(object): |
| 104 | 69 | self.index = 0 |
| 105 | 70 | self.line = 0 |
| 106 | 71 | self.column = 0 |
| 107 | | if isinstance(stream, unicode): |
| | 72 | if isinstance(stream, str): |
| 108 | 73 | self.name = "<unicode string>" |
| 109 | 74 | self.check_printable(stream) |
| 110 | | self.buffer = stream+u'\0' |
| 111 | | elif isinstance(stream, str): |
| | 75 | self.buffer = stream+'\0' |
| | 76 | elif isinstance(stream, bytes): |
| 112 | 77 | self.name = "<string>" |
| 113 | 78 | self.raw_buffer = stream |
| 114 | 79 | self.determine_encoding() |
| … |
… |
class Reader(object): |
| 116 | 81 | self.stream = stream |
| 117 | 82 | self.name = getattr(stream, 'name', "<file>") |
| 118 | 83 | self.eof = False |
| 119 | | self.raw_buffer = '' |
| | 84 | self.raw_buffer = None |
| 120 | 85 | self.determine_encoding() |
| 121 | 86 | |
| 122 | 87 | def peek(self, index=0): |
| … |
… |
class Reader(object): |
| 138 | 103 | ch = self.buffer[self.pointer] |
| 139 | 104 | self.pointer += 1 |
| 140 | 105 | self.index += 1 |
| 141 | | if ch in u'\n\x85\u2028\u2029' \ |
| 142 | | or (ch == u'\r' and self.buffer[self.pointer] != u'\n'): |
| | 106 | if ch in '\n\x85\u2028\u2029' \ |
| | 107 | or (ch == '\r' and self.buffer[self.pointer] != '\n'): |
| 143 | 108 | self.line += 1 |
| 144 | 109 | self.column = 0 |
| 145 | | elif ch != u'\uFEFF': |
| | 110 | elif ch != '\uFEFF': |
| 146 | 111 | self.column += 1 |
| 147 | 112 | length -= 1 |
| 148 | 113 | |
| … |
… |
class Reader(object): |
| 155 | 120 | None, None) |
| 156 | 121 | |
| 157 | 122 | def determine_encoding(self): |
| 158 | | while not self.eof and len(self.raw_buffer) < 2: |
| | 123 | while not self.eof and (self.raw_buffer is None or len(self.raw_buffer) < 2): |
| 159 | 124 | self.update_raw() |
| 160 | | if not isinstance(self.raw_buffer, unicode): |
| | 125 | if not isinstance(self.raw_buffer, str): |
| 161 | 126 | if self.raw_buffer.startswith(codecs.BOM_UTF16_LE): |
| 162 | | self.raw_decode = utf_16_le_decode |
| | 127 | self.raw_decode = codecs.utf_16_le_decode |
| 163 | 128 | self.encoding = 'utf-16-le' |
| 164 | 129 | elif self.raw_buffer.startswith(codecs.BOM_UTF16_BE): |
| 165 | | self.raw_decode = utf_16_be_decode |
| | 130 | self.raw_decode = codecs.utf_16_be_decode |
| 166 | 131 | self.encoding = 'utf-16-be' |
| 167 | 132 | else: |
| 168 | | self.raw_decode = utf_8_decode |
| | 133 | self.raw_decode = codecs.utf_8_decode |
| 169 | 134 | self.encoding = 'utf-8' |
| 170 | 135 | self.update(1) |
| 171 | 136 | |
| 172 | | NON_PRINTABLE = re.compile(u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD]') |
| | 137 | NON_PRINTABLE = re.compile('[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD]') |
| 173 | 138 | def check_printable(self, data): |
| 174 | 139 | match = self.NON_PRINTABLE.search(data) |
| 175 | 140 | if match: |
| … |
… |
class Reader(object): |
| 190 | 155 | try: |
| 191 | 156 | data, converted = self.raw_decode(self.raw_buffer, |
| 192 | 157 | 'strict', self.eof) |
| 193 | | except UnicodeDecodeError, exc: |
| | 158 | except UnicodeDecodeError as exc: |
| 194 | 159 | character = exc.object[exc.start] |
| 195 | 160 | if self.stream is not None: |
| 196 | 161 | position = self.stream_pointer-len(self.raw_buffer)+exc.start |
| 197 | 162 | else: |
| 198 | 163 | position = exc.start |
| 199 | 164 | raise ReaderError(self.name, position, character, |
| 200 | | exc.encoding, exc.reason) |
| | 165 | exc.encoding, exc.reason) from exc |
| 201 | 166 | else: |
| 202 | 167 | data = self.raw_buffer |
| 203 | 168 | converted = len(data) |
| … |
… |
class Reader(object): |
| 205 | 170 | self.buffer += data |
| 206 | 171 | self.raw_buffer = self.raw_buffer[converted:] |
| 207 | 172 | if self.eof: |
| 208 | | self.buffer += u'\0' |
| | 173 | self.buffer += '\0' |
| 209 | 174 | self.raw_buffer = None |
| 210 | 175 | break |
| 211 | 176 | |
| 212 | 177 | def update_raw(self, size=1024): |
| 213 | 178 | data = self.stream.read(size) |
| 214 | 179 | if data: |
| 215 | | self.raw_buffer += data |
| 216 | | self.stream_pointer += len(data) |
| | 180 | if self.raw_buffer is None: |
| | 181 | self.raw_buffer = data |
| | 182 | else: |
| | 183 | self.raw_buffer += data |
| | 184 | self.stream_pointer += len(data) |
| 217 | 185 | else: |
| | 186 | if self.raw_buffer is None: |
| | 187 | self.raw_buffer = b'' |
| 218 | 188 | self.eof = True |
| 219 | 189 | |
| 220 | 190 | #try: |
-
diff --git lib/yaml/representer.py lib/yaml/representer.py
index 1f4fe59..5c9a76f 100644
|
|
|
|
| 2 | 2 | __all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer', |
| 3 | 3 | 'RepresenterError'] |
| 4 | 4 | |
| 5 | | from error import * |
| 6 | | from nodes import * |
| | 5 | from yaml.error import * |
| | 6 | from yaml.nodes import * |
| 7 | 7 | |
| 8 | | import datetime |
| | 8 | import datetime, base64 |
| 9 | 9 | |
| 10 | | try: |
| 11 | | set |
| 12 | | except NameError: |
| 13 | | from sets import Set as set |
| 14 | | |
| 15 | | import sys, copy_reg, types |
| | 10 | import sys, copyreg, types |
| 16 | 11 | |
| 17 | 12 | class RepresenterError(YAMLError): |
| 18 | 13 | pass |
| 19 | 14 | |
| 20 | | class BaseRepresenter(object): |
| | 15 | class BaseRepresenter: |
| 21 | 16 | |
| 22 | 17 | yaml_representers = {} |
| 23 | 18 | yaml_multi_representers = {} |
| … |
… |
class BaseRepresenter(object): |
| 56 | 51 | #self.represented_objects[alias_key] = None |
| 57 | 52 | self.object_keeper.append(data) |
| 58 | 53 | data_types = type(data).__mro__ |
| 59 | | if type(data) is types.InstanceType: |
| 60 | | data_types = self.get_classobj_bases(data.__class__)+list(data_types) |
| 61 | 54 | if data_types[0] in self.yaml_representers: |
| 62 | 55 | node = self.yaml_representers[data_types[0]](self, data) |
| 63 | 56 | else: |
| … |
… |
class BaseRepresenter(object): |
| 71 | 64 | elif None in self.yaml_representers: |
| 72 | 65 | node = self.yaml_representers[None](self, data) |
| 73 | 66 | else: |
| 74 | | node = ScalarNode(None, unicode(data)) |
| | 67 | node = ScalarNode(None, str(data)) |
| 75 | 68 | #if alias_key is not None: |
| 76 | 69 | # self.represented_objects[alias_key] = node |
| 77 | 70 | return node |
| … |
… |
class BaseRepresenter(object): |
| 121 | 114 | self.represented_objects[self.alias_key] = node |
| 122 | 115 | best_style = True |
| 123 | 116 | if hasattr(mapping, 'items'): |
| 124 | | mapping = mapping.items() |
| 125 | | mapping.sort() |
| | 117 | mapping = list(mapping.items()) |
| 126 | 118 | for item_key, item_value in mapping: |
| 127 | 119 | node_key = self.represent_data(item_key) |
| 128 | 120 | node_value = self.represent_data(item_value) |
| … |
… |
class BaseRepresenter(object): |
| 131 | 123 | if not (isinstance(node_value, ScalarNode) and not node_value.style): |
| 132 | 124 | best_style = False |
| 133 | 125 | value.append((node_key, node_value)) |
| | 126 | value.sort() |
| 134 | 127 | if flow_style is None: |
| 135 | 128 | if self.default_flow_style is not None: |
| 136 | 129 | node.flow_style = self.default_flow_style |
| … |
… |
class SafeRepresenter(BaseRepresenter): |
| 146 | 139 | def ignore_aliases(self, data): |
| 147 | 140 | if data in [None, ()]: |
| 148 | 141 | return True |
| 149 | | if isinstance(data, (str, unicode, bool, int, float)): |
| | 142 | if isinstance(data, (str, bytes, bool, int, float)): |
| 150 | 143 | return True |
| 151 | 144 | |
| 152 | 145 | def represent_none(self, data): |
| 153 | | return self.represent_scalar(u'tag:yaml.org,2002:null', |
| 154 | | u'null') |
| | 146 | return self.represent_scalar('tag:yaml.org,2002:null', |
| | 147 | 'null') |
| 155 | 148 | |
| 156 | | def represent_str(self, data): |
| | 149 | def represent_bytes(self, data): |
| 157 | 150 | tag = None |
| 158 | 151 | style = None |
| 159 | 152 | try: |
| 160 | | data = unicode(data, 'ascii') |
| 161 | | tag = u'tag:yaml.org,2002:str' |
| | 153 | data = data.decode('ascii') |
| | 154 | tag = 'tag:yaml.org,2002:python/bytes' |
| 162 | 155 | except UnicodeDecodeError: |
| 163 | 156 | try: |
| 164 | | data = unicode(data, 'utf-8') |
| 165 | | tag = u'tag:yaml.org,2002:str' |
| | 157 | data = data.decode('utf-8') |
| | 158 | tag = 'tag:yaml.org,2002:python/bytes' |
| 166 | 159 | except UnicodeDecodeError: |
| 167 | | data = data.encode('base64') |
| 168 | | tag = u'tag:yaml.org,2002:binary' |
| | 160 | data = base64.b64encode(data).decode('ascii') |
| | 161 | tag = 'tag:yaml.org,2002:binary' |
| 169 | 162 | style = '|' |
| 170 | 163 | return self.represent_scalar(tag, data, style=style) |
| 171 | 164 | |
| 172 | | def represent_unicode(self, data): |
| 173 | | return self.represent_scalar(u'tag:yaml.org,2002:str', data) |
| | 165 | def represent_str(self, data): |
| | 166 | return self.represent_scalar('tag:yaml.org,2002:str', data) |
| 174 | 167 | |
| 175 | 168 | def represent_bool(self, data): |
| 176 | 169 | if data: |
| 177 | | value = u'true' |
| | 170 | value = 'true' |
| 178 | 171 | else: |
| 179 | | value = u'false' |
| 180 | | return self.represent_scalar(u'tag:yaml.org,2002:bool', value) |
| | 172 | value = 'false' |
| | 173 | return self.represent_scalar('tag:yaml.org,2002:bool', value) |
| 181 | 174 | |
| 182 | 175 | def represent_int(self, data): |
| 183 | | return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) |
| 184 | | |
| 185 | | def represent_long(self, data): |
| 186 | | return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) |
| | 176 | return self.represent_scalar('tag:yaml.org,2002:int', str(data)) |
| 187 | 177 | |
| 188 | 178 | inf_value = 1e300 |
| 189 | 179 | while repr(inf_value) != repr(inf_value*inf_value): |
| … |
… |
class SafeRepresenter(BaseRepresenter): |
| 191 | 181 | |
| 192 | 182 | def represent_float(self, data): |
| 193 | 183 | if data != data or (data == 0.0 and data == 1.0): |
| 194 | | value = u'.nan' |
| | 184 | value = '.nan' |
| 195 | 185 | elif data == self.inf_value: |
| 196 | | value = u'.inf' |
| | 186 | value = '.inf' |
| 197 | 187 | elif data == -self.inf_value: |
| 198 | | value = u'-.inf' |
| | 188 | value = '-.inf' |
| 199 | 189 | else: |
| 200 | | value = unicode(repr(data)).lower() |
| | 190 | value = str(repr(data)).lower() |
| 201 | 191 | # Note that in some cases `repr(data)` represents a float number |
| 202 | 192 | # without the decimal parts. For instance: |
| 203 | 193 | # >>> repr(1e17) |
| … |
… |
class SafeRepresenter(BaseRepresenter): |
| 205 | 195 | # Unfortunately, this is not a valid float representation according |
| 206 | 196 | # to the definition of the `!!float` tag. We fix this by adding |
| 207 | 197 | # '.0' before the 'e' symbol. |
| 208 | | if u'.' not in value and u'e' in value: |
| 209 | | value = value.replace(u'e', u'.0e', 1) |
| 210 | | return self.represent_scalar(u'tag:yaml.org,2002:float', value) |
| | 198 | if '.' not in value and 'e' in value: |
| | 199 | value = value.replace('e', '.0e', 1) |
| | 200 | return self.represent_scalar('tag:yaml.org,2002:float', value) |
| 211 | 201 | |
| 212 | 202 | def represent_list(self, data): |
| 213 | 203 | #pairs = (len(data) > 0 and isinstance(data, list)) |
| … |
… |
class SafeRepresenter(BaseRepresenter): |
| 217 | 207 | # pairs = False |
| 218 | 208 | # break |
| 219 | 209 | #if not pairs: |
| 220 | | return self.represent_sequence(u'tag:yaml.org,2002:seq', data) |
| | 210 | return self.represent_sequence('tag:yaml.org,2002:seq', data) |
| 221 | 211 | #value = [] |
| 222 | 212 | #for item_key, item_value in data: |
| 223 | | # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', |
| | 213 | # value.append(self.represent_mapping('tag:yaml.org,2002:map', |
| 224 | 214 | # [(item_key, item_value)])) |
| 225 | | #return SequenceNode(u'tag:yaml.org,2002:pairs', value) |
| | 215 | #return SequenceNode('tag:yaml.org,2002:pairs', value) |
| 226 | 216 | |
| 227 | 217 | def represent_dict(self, data): |
| 228 | | return self.represent_mapping(u'tag:yaml.org,2002:map', data) |
| | 218 | return self.represent_mapping('tag:yaml.org,2002:map', data) |
| 229 | 219 | |
| 230 | 220 | def represent_set(self, data): |
| 231 | 221 | value = {} |
| 232 | 222 | for key in data: |
| 233 | 223 | value[key] = None |
| 234 | | return self.represent_mapping(u'tag:yaml.org,2002:set', value) |
| | 224 | return self.represent_mapping('tag:yaml.org,2002:set', value) |
| 235 | 225 | |
| 236 | 226 | def represent_date(self, data): |
| 237 | | value = unicode(data.isoformat()) |
| 238 | | return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) |
| | 227 | value = str(data.isoformat()) |
| | 228 | return self.represent_scalar('tag:yaml.org,2002:timestamp', value) |
| 239 | 229 | |
| 240 | 230 | def represent_datetime(self, data): |
| 241 | | value = unicode(data.isoformat(' ')) |
| 242 | | return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) |
| | 231 | value = str(data.isoformat(' ')) |
| | 232 | return self.represent_scalar('tag:yaml.org,2002:timestamp', value) |
| 243 | 233 | |
| 244 | 234 | def represent_yaml_object(self, tag, data, cls, flow_style=None): |
| 245 | 235 | if hasattr(data, '__getstate__'): |
| … |
… |
SafeRepresenter.add_representer(type(None), |
| 257 | 247 | SafeRepresenter.add_representer(str, |
| 258 | 248 | SafeRepresenter.represent_str) |
| 259 | 249 | |
| 260 | | SafeRepresenter.add_representer(unicode, |
| 261 | | SafeRepresenter.represent_unicode) |
| 262 | | |
| 263 | 250 | SafeRepresenter.add_representer(bool, |
| 264 | 251 | SafeRepresenter.represent_bool) |
| 265 | 252 | |
| 266 | 253 | SafeRepresenter.add_representer(int, |
| 267 | 254 | SafeRepresenter.represent_int) |
| 268 | 255 | |
| 269 | | SafeRepresenter.add_representer(long, |
| 270 | | SafeRepresenter.represent_long) |
| 271 | | |
| 272 | 256 | SafeRepresenter.add_representer(float, |
| 273 | 257 | SafeRepresenter.represent_float) |
| 274 | 258 | |
| … |
… |
SafeRepresenter.add_representer(None, |
| 294 | 278 | |
| 295 | 279 | class Representer(SafeRepresenter): |
| 296 | 280 | |
| 297 | | def represent_str(self, data): |
| | 281 | def represent_bytes(self, data): |
| 298 | 282 | tag = None |
| 299 | 283 | style = None |
| 300 | 284 | try: |
| 301 | | data = unicode(data, 'ascii') |
| 302 | | tag = u'tag:yaml.org,2002:str' |
| | 285 | data = data.decode('ascii') |
| | 286 | tag = 'tag:yaml.org,2002:python/bytes' |
| 303 | 287 | except UnicodeDecodeError: |
| 304 | 288 | try: |
| 305 | | data = unicode(data, 'utf-8') |
| 306 | | tag = u'tag:yaml.org,2002:python/str' |
| | 289 | data = data.decode('utf-8') |
| | 290 | tag = 'tag:yaml.org,2002:python/bytes' |
| 307 | 291 | except UnicodeDecodeError: |
| 308 | | data = data.encode('base64') |
| 309 | | tag = u'tag:yaml.org,2002:binary' |
| | 292 | data = base64.b64encode(data).decode('ascii') |
| | 293 | tag = 'tag:yaml.org,2002:binary' |
| 310 | 294 | style = '|' |
| 311 | 295 | return self.represent_scalar(tag, data, style=style) |
| 312 | 296 | |
| 313 | | def represent_unicode(self, data): |
| 314 | | tag = None |
| 315 | | try: |
| 316 | | data.encode('ascii') |
| 317 | | tag = u'tag:yaml.org,2002:python/unicode' |
| 318 | | except UnicodeEncodeError: |
| 319 | | tag = u'tag:yaml.org,2002:str' |
| | 297 | def represent_str(self, data): |
| | 298 | tag = 'tag:yaml.org,2002:str' |
| 320 | 299 | return self.represent_scalar(tag, data) |
| 321 | 300 | |
| 322 | | def represent_long(self, data): |
| 323 | | tag = u'tag:yaml.org,2002:int' |
| 324 | | if int(data) is not data: |
| 325 | | tag = u'tag:yaml.org,2002:python/long' |
| 326 | | return self.represent_scalar(tag, unicode(data)) |
| 327 | | |
| 328 | 301 | def represent_complex(self, data): |
| 329 | 302 | if data.imag == 0.0: |
| 330 | | data = u'%r' % data.real |
| | 303 | data = '%r' % data.real |
| 331 | 304 | elif data.real == 0.0: |
| 332 | | data = u'%rj' % data.imag |
| | 305 | data = '%rj' % data.imag |
| 333 | 306 | elif data.imag > 0: |
| 334 | | data = u'%r+%rj' % (data.real, data.imag) |
| | 307 | data = '%r+%rj' % (data.real, data.imag) |
| 335 | 308 | else: |
| 336 | | data = u'%r%rj' % (data.real, data.imag) |
| 337 | | return self.represent_scalar(u'tag:yaml.org,2002:python/complex', data) |
| | 309 | data = '%r%rj' % (data.real, data.imag) |
| | 310 | return self.represent_scalar('tag:yaml.org,2002:python/complex', data) |
| 338 | 311 | |
| 339 | 312 | def represent_tuple(self, data): |
| 340 | | return self.represent_sequence(u'tag:yaml.org,2002:python/tuple', data) |
| | 313 | return self.represent_sequence('tag:yaml.org,2002:python/tuple', data) |
| 341 | 314 | |
| 342 | 315 | def represent_name(self, data): |
| 343 | | name = u'%s.%s' % (data.__module__, data.__name__) |
| 344 | | return self.represent_scalar(u'tag:yaml.org,2002:python/name:'+name, u'') |
| | 316 | name = '%s.%s' % (data.__module__, data.__name__) |
| | 317 | return self.represent_scalar('tag:yaml.org,2002:python/name:'+name, '') |
| 345 | 318 | |
| 346 | 319 | def represent_module(self, data): |
| 347 | 320 | return self.represent_scalar( |
| 348 | | u'tag:yaml.org,2002:python/module:'+data.__name__, u'') |
| 349 | | |
| 350 | | def represent_instance(self, data): |
| 351 | | # For instances of classic classes, we use __getinitargs__ and |
| 352 | | # __getstate__ to serialize the data. |
| 353 | | |
| 354 | | # If data.__getinitargs__ exists, the object must be reconstructed by |
| 355 | | # calling cls(**args), where args is a tuple returned by |
| 356 | | # __getinitargs__. Otherwise, the cls.__init__ method should never be |
| 357 | | # called and the class instance is created by instantiating a trivial |
| 358 | | # class and assigning to the instance's __class__ variable. |
| 359 | | |
| 360 | | # If data.__getstate__ exists, it returns the state of the object. |
| 361 | | # Otherwise, the state of the object is data.__dict__. |
| 362 | | |
| 363 | | # We produce either a !!python/object or !!python/object/new node. |
| 364 | | # If data.__getinitargs__ does not exist and state is a dictionary, we |
| 365 | | # produce a !!python/object node . Otherwise we produce a |
| 366 | | # !!python/object/new node. |
| 367 | | |
| 368 | | cls = data.__class__ |
| 369 | | class_name = u'%s.%s' % (cls.__module__, cls.__name__) |
| 370 | | args = None |
| 371 | | state = None |
| 372 | | if hasattr(data, '__getinitargs__'): |
| 373 | | args = list(data.__getinitargs__()) |
| 374 | | if hasattr(data, '__getstate__'): |
| 375 | | state = data.__getstate__() |
| 376 | | else: |
| 377 | | state = data.__dict__ |
| 378 | | if args is None and isinstance(state, dict): |
| 379 | | return self.represent_mapping( |
| 380 | | u'tag:yaml.org,2002:python/object:'+class_name, state) |
| 381 | | if isinstance(state, dict) and not state: |
| 382 | | return self.represent_sequence( |
| 383 | | u'tag:yaml.org,2002:python/object/new:'+class_name, args) |
| 384 | | value = {} |
| 385 | | if args: |
| 386 | | value['args'] = args |
| 387 | | value['state'] = state |
| 388 | | return self.represent_mapping( |
| 389 | | u'tag:yaml.org,2002:python/object/new:'+class_name, value) |
| | 321 | 'tag:yaml.org,2002:python/module:'+data.__name__, '') |
| 390 | 322 | |
| 391 | 323 | def represent_object(self, data): |
| 392 | 324 | # We use __reduce__ API to save the data. data.__reduce__ returns |
| … |
… |
class Representer(SafeRepresenter): |
| 406 | 338 | # !!python/object/apply node. |
| 407 | 339 | |
| 408 | 340 | cls = type(data) |
| 409 | | if cls in copy_reg.dispatch_table: |
| 410 | | reduce = copy_reg.dispatch_table[cls](data) |
| | 341 | if cls in copyreg.dispatch_table: |
| | 342 | reduce = copyreg.dispatch_table[cls](data) |
| 411 | 343 | elif hasattr(data, '__reduce_ex__'): |
| 412 | 344 | reduce = data.__reduce_ex__(2) |
| 413 | 345 | elif hasattr(data, '__reduce__'): |
| … |
… |
class Representer(SafeRepresenter): |
| 426 | 358 | if function.__name__ == '__newobj__': |
| 427 | 359 | function = args[0] |
| 428 | 360 | args = args[1:] |
| 429 | | tag = u'tag:yaml.org,2002:python/object/new:' |
| | 361 | tag = 'tag:yaml.org,2002:python/object/new:' |
| 430 | 362 | newobj = True |
| 431 | 363 | else: |
| 432 | | tag = u'tag:yaml.org,2002:python/object/apply:' |
| | 364 | tag = 'tag:yaml.org,2002:python/object/apply:' |
| 433 | 365 | newobj = False |
| 434 | | function_name = u'%s.%s' % (function.__module__, function.__name__) |
| | 366 | function_name = '%s.%s' % (function.__module__, function.__name__) |
| 435 | 367 | if not args and not listitems and not dictitems \ |
| 436 | 368 | and isinstance(state, dict) and newobj: |
| 437 | 369 | return self.represent_mapping( |
| 438 | | u'tag:yaml.org,2002:python/object:'+function_name, state) |
| | 370 | 'tag:yaml.org,2002:python/object:'+function_name, state) |
| 439 | 371 | if not listitems and not dictitems \ |
| 440 | 372 | and isinstance(state, dict) and not state: |
| 441 | 373 | return self.represent_sequence(tag+function_name, args) |
| … |
… |
class Representer(SafeRepresenter): |
| 453 | 385 | Representer.add_representer(str, |
| 454 | 386 | Representer.represent_str) |
| 455 | 387 | |
| 456 | | Representer.add_representer(unicode, |
| 457 | | Representer.represent_unicode) |
| 458 | | |
| 459 | | Representer.add_representer(long, |
| 460 | | Representer.represent_long) |
| | 388 | Representer.add_representer(bytes, |
| | 389 | Representer.represent_bytes) |
| 461 | 390 | |
| 462 | 391 | Representer.add_representer(complex, |
| 463 | 392 | Representer.represent_complex) |
| … |
… |
Representer.add_representer(tuple, |
| 468 | 397 | Representer.add_representer(type, |
| 469 | 398 | Representer.represent_name) |
| 470 | 399 | |
| 471 | | Representer.add_representer(types.ClassType, |
| 472 | | Representer.represent_name) |
| 473 | | |
| 474 | 400 | Representer.add_representer(types.FunctionType, |
| 475 | 401 | Representer.represent_name) |
| 476 | 402 | |
| … |
… |
Representer.add_representer(types.BuiltinFunctionType, |
| 480 | 406 | Representer.add_representer(types.ModuleType, |
| 481 | 407 | Representer.represent_module) |
| 482 | 408 | |
| 483 | | Representer.add_multi_representer(types.InstanceType, |
| 484 | | Representer.represent_instance) |
| 485 | | |
| 486 | 409 | Representer.add_multi_representer(object, |
| 487 | 410 | Representer.represent_object) |
| 488 | 411 | |
-
diff --git lib/yaml/resolver.py lib/yaml/resolver.py
index 60c43e3..08f121f 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['BaseResolver', 'Resolver'] |
| 3 | 3 | |
| 4 | | from error import * |
| 5 | | from nodes import * |
| | 4 | from yaml.error import * |
| | 5 | from yaml.nodes import * |
| 6 | 6 | |
| 7 | 7 | import re |
| 8 | 8 | |
| 9 | 9 | class ResolverError(YAMLError): |
| 10 | 10 | pass |
| 11 | 11 | |
| 12 | | class BaseResolver(object): |
| | 12 | class BaseResolver: |
| 13 | 13 | |
| 14 | | DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' |
| 15 | | DEFAULT_SEQUENCE_TAG = u'tag:yaml.org,2002:seq' |
| 16 | | DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' |
| | 14 | DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str' |
| | 15 | DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq' |
| | 16 | DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map' |
| 17 | 17 | |
| 18 | 18 | yaml_implicit_resolvers = {} |
| 19 | 19 | yaml_path_resolvers = {} |
| … |
… |
class BaseResolver(object): |
| 66 | 66 | elif node_check is dict: |
| 67 | 67 | node_check = MappingNode |
| 68 | 68 | elif node_check not in [ScalarNode, SequenceNode, MappingNode] \ |
| 69 | | and not isinstance(node_check, basestring) \ |
| | 69 | and not isinstance(node_check, str) \ |
| 70 | 70 | and node_check is not None: |
| 71 | 71 | raise ResolverError("Invalid node checker: %s" % node_check) |
| 72 | | if not isinstance(index_check, (basestring, int)) \ |
| | 72 | if not isinstance(index_check, (str, int)) \ |
| 73 | 73 | and index_check is not None: |
| 74 | 74 | raise ResolverError("Invalid index checker: %s" % index_check) |
| 75 | 75 | new_path.append((node_check, index_check)) |
| … |
… |
class BaseResolver(object): |
| 117 | 117 | def check_resolver_prefix(self, depth, path, kind, |
| 118 | 118 | current_node, current_index): |
| 119 | 119 | node_check, index_check = path[depth-1] |
| 120 | | if isinstance(node_check, basestring): |
| | 120 | if isinstance(node_check, str): |
| 121 | 121 | if current_node.tag != node_check: |
| 122 | 122 | return |
| 123 | 123 | elif node_check is not None: |
| … |
… |
class BaseResolver(object): |
| 128 | 128 | if (index_check is False or index_check is None) \ |
| 129 | 129 | and current_index is None: |
| 130 | 130 | return |
| 131 | | if isinstance(index_check, basestring): |
| | 131 | if isinstance(index_check, str): |
| 132 | 132 | if not (isinstance(current_index, ScalarNode) |
| 133 | 133 | and index_check == current_index.value): |
| 134 | 134 | return |
| … |
… |
class BaseResolver(object): |
| 139 | 139 | |
| 140 | 140 | def resolve(self, kind, value, implicit): |
| 141 | 141 | if kind is ScalarNode and implicit[0]: |
| 142 | | if value == u'': |
| 143 | | resolvers = self.yaml_implicit_resolvers.get(u'', []) |
| | 142 | if value == '': |
| | 143 | resolvers = self.yaml_implicit_resolvers.get('', []) |
| 144 | 144 | else: |
| 145 | 145 | resolvers = self.yaml_implicit_resolvers.get(value[0], []) |
| 146 | 146 | resolvers += self.yaml_implicit_resolvers.get(None, []) |
| … |
… |
class Resolver(BaseResolver): |
| 165 | 165 | pass |
| 166 | 166 | |
| 167 | 167 | Resolver.add_implicit_resolver( |
| 168 | | u'tag:yaml.org,2002:bool', |
| 169 | | re.compile(ur'''^(?:yes|Yes|YES|no|No|NO |
| | 168 | 'tag:yaml.org,2002:bool', |
| | 169 | re.compile(r'''^(?:yes|Yes|YES|no|No|NO |
| 170 | 170 | |true|True|TRUE|false|False|FALSE |
| 171 | 171 | |on|On|ON|off|Off|OFF)$''', re.X), |
| 172 | | list(u'yYnNtTfFoO')) |
| | 172 | list('yYnNtTfFoO')) |
| 173 | 173 | |
| 174 | 174 | Resolver.add_implicit_resolver( |
| 175 | | u'tag:yaml.org,2002:float', |
| 176 | | re.compile(ur'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? |
| | 175 | 'tag:yaml.org,2002:float', |
| | 176 | re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? |
| 177 | 177 | |\.[0-9_]+(?:[eE][-+][0-9]+)? |
| 178 | 178 | |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]* |
| 179 | 179 | |[-+]?\.(?:inf|Inf|INF) |
| 180 | 180 | |\.(?:nan|NaN|NAN))$''', re.X), |
| 181 | | list(u'-+0123456789.')) |
| | 181 | list('-+0123456789.')) |
| 182 | 182 | |
| 183 | 183 | Resolver.add_implicit_resolver( |
| 184 | | u'tag:yaml.org,2002:int', |
| 185 | | re.compile(ur'''^(?:[-+]?0b[0-1_]+ |
| | 184 | 'tag:yaml.org,2002:int', |
| | 185 | re.compile(r'''^(?:[-+]?0b[0-1_]+ |
| 186 | 186 | |[-+]?0[0-7_]+ |
| 187 | 187 | |[-+]?(?:0|[1-9][0-9_]*) |
| 188 | 188 | |[-+]?0x[0-9a-fA-F_]+ |
| 189 | 189 | |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X), |
| 190 | | list(u'-+0123456789')) |
| | 190 | list('-+0123456789')) |
| 191 | 191 | |
| 192 | 192 | Resolver.add_implicit_resolver( |
| 193 | | u'tag:yaml.org,2002:merge', |
| 194 | | re.compile(ur'^(?:<<)$'), |
| | 193 | 'tag:yaml.org,2002:merge', |
| | 194 | re.compile(r'^(?:<<)$'), |
| 195 | 195 | ['<']) |
| 196 | 196 | |
| 197 | 197 | Resolver.add_implicit_resolver( |
| 198 | | u'tag:yaml.org,2002:null', |
| 199 | | re.compile(ur'''^(?: ~ |
| | 198 | 'tag:yaml.org,2002:null', |
| | 199 | re.compile(r'''^(?: ~ |
| 200 | 200 | |null|Null|NULL |
| 201 | 201 | | )$''', re.X), |
| 202 | | [u'~', u'n', u'N', u'']) |
| | 202 | ['~', 'n', 'N', '']) |
| 203 | 203 | |
| 204 | 204 | Resolver.add_implicit_resolver( |
| 205 | | u'tag:yaml.org,2002:timestamp', |
| 206 | | re.compile(ur'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] |
| | 205 | 'tag:yaml.org,2002:timestamp', |
| | 206 | re.compile(r'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] |
| 207 | 207 | |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]? |
| 208 | 208 | (?:[Tt]|[ \t]+)[0-9][0-9]? |
| 209 | 209 | :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)? |
| 210 | 210 | (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X), |
| 211 | | list(u'0123456789')) |
| | 211 | list('0123456789')) |
| 212 | 212 | |
| 213 | 213 | Resolver.add_implicit_resolver( |
| 214 | | u'tag:yaml.org,2002:value', |
| 215 | | re.compile(ur'^(?:=)$'), |
| | 214 | 'tag:yaml.org,2002:value', |
| | 215 | re.compile(r'^(?:=)$'), |
| 216 | 216 | ['=']) |
| 217 | 217 | |
| 218 | 218 | # The following resolver is only for documentation purposes. It cannot work |
| 219 | 219 | # because plain scalars cannot start with '!', '&', or '*'. |
| 220 | 220 | Resolver.add_implicit_resolver( |
| 221 | | u'tag:yaml.org,2002:yaml', |
| 222 | | re.compile(ur'^(?:!|&|\*)$'), |
| 223 | | list(u'!&*')) |
| | 221 | 'tag:yaml.org,2002:yaml', |
| | 222 | re.compile(r'^(?:!|&|\*)$'), |
| | 223 | list('!&*')) |
| 224 | 224 | |
-
diff --git lib/yaml/scanner.py lib/yaml/scanner.py
index a3ecdd0..2014e46 100644
|
|
|
|
| 26 | 26 | |
| 27 | 27 | __all__ = ['Scanner', 'ScannerError'] |
| 28 | 28 | |
| 29 | | from error import MarkedYAMLError |
| 30 | | from tokens import * |
| | 29 | from yaml.error import MarkedYAMLError |
| | 30 | from yaml.tokens import * |
| 31 | 31 | |
| 32 | 32 | class ScannerError(MarkedYAMLError): |
| 33 | 33 | pass |
| 34 | 34 | |
| 35 | | class SimpleKey(object): |
| | 35 | class SimpleKey: |
| 36 | 36 | # See below simple keys treatment. |
| 37 | 37 | |
| 38 | 38 | def __init__(self, token_number, required, index, line, column, mark): |
| … |
… |
class SimpleKey(object): |
| 43 | 43 | self.column = column |
| 44 | 44 | self.mark = mark |
| 45 | 45 | |
| 46 | | class Scanner(object): |
| | 46 | class Scanner: |
| 47 | 47 | |
| 48 | 48 | def __init__(self): |
| 49 | 49 | """Initialize the scanner.""" |
| … |
… |
class Scanner(object): |
| 166 | 166 | ch = self.peek() |
| 167 | 167 | |
| 168 | 168 | # Is it the end of stream? |
| 169 | | if ch == u'\0': |
| | 169 | if ch == '\0': |
| 170 | 170 | return self.fetch_stream_end() |
| 171 | 171 | |
| 172 | 172 | # Is it a directive? |
| 173 | | if ch == u'%' and self.check_directive(): |
| | 173 | if ch == '%' and self.check_directive(): |
| 174 | 174 | return self.fetch_directive() |
| 175 | 175 | |
| 176 | 176 | # Is it the document start? |
| 177 | | if ch == u'-' and self.check_document_start(): |
| | 177 | if ch == '-' and self.check_document_start(): |
| 178 | 178 | return self.fetch_document_start() |
| 179 | 179 | |
| 180 | 180 | # Is it the document end? |
| 181 | | if ch == u'.' and self.check_document_end(): |
| | 181 | if ch == '.' and self.check_document_end(): |
| 182 | 182 | return self.fetch_document_end() |
| 183 | 183 | |
| 184 | 184 | # TODO: support for BOM within a stream. |
| 185 | | #if ch == u'\uFEFF': |
| | 185 | #if ch == '\uFEFF': |
| 186 | 186 | # return self.fetch_bom() <-- issue BOMToken |
| 187 | 187 | |
| 188 | 188 | # Note: the order of the following checks is NOT significant. |
| 189 | 189 | |
| 190 | 190 | # Is it the flow sequence start indicator? |
| 191 | | if ch == u'[': |
| | 191 | if ch == '[': |
| 192 | 192 | return self.fetch_flow_sequence_start() |
| 193 | 193 | |
| 194 | 194 | # Is it the flow mapping start indicator? |
| 195 | | if ch == u'{': |
| | 195 | if ch == '{': |
| 196 | 196 | return self.fetch_flow_mapping_start() |
| 197 | 197 | |
| 198 | 198 | # Is it the flow sequence end indicator? |
| 199 | | if ch == u']': |
| | 199 | if ch == ']': |
| 200 | 200 | return self.fetch_flow_sequence_end() |
| 201 | 201 | |
| 202 | 202 | # Is it the flow mapping end indicator? |
| 203 | | if ch == u'}': |
| | 203 | if ch == '}': |
| 204 | 204 | return self.fetch_flow_mapping_end() |
| 205 | 205 | |
| 206 | 206 | # Is it the flow entry indicator? |
| 207 | | if ch == u',': |
| | 207 | if ch == ',': |
| 208 | 208 | return self.fetch_flow_entry() |
| 209 | 209 | |
| 210 | 210 | # Is it the block entry indicator? |
| 211 | | if ch == u'-' and self.check_block_entry(): |
| | 211 | if ch == '-' and self.check_block_entry(): |
| 212 | 212 | return self.fetch_block_entry() |
| 213 | 213 | |
| 214 | 214 | # Is it the key indicator? |
| 215 | | if ch == u'?' and self.check_key(): |
| | 215 | if ch == '?' and self.check_key(): |
| 216 | 216 | return self.fetch_key() |
| 217 | 217 | |
| 218 | 218 | # Is it the value indicator? |
| 219 | | if ch == u':' and self.check_value(): |
| | 219 | if ch == ':' and self.check_value(): |
| 220 | 220 | return self.fetch_value() |
| 221 | 221 | |
| 222 | 222 | # Is it an alias? |
| 223 | | if ch == u'*': |
| | 223 | if ch == '*': |
| 224 | 224 | return self.fetch_alias() |
| 225 | 225 | |
| 226 | 226 | # Is it an anchor? |
| 227 | | if ch == u'&': |
| | 227 | if ch == '&': |
| 228 | 228 | return self.fetch_anchor() |
| 229 | 229 | |
| 230 | 230 | # Is it a tag? |
| 231 | | if ch == u'!': |
| | 231 | if ch == '!': |
| 232 | 232 | return self.fetch_tag() |
| 233 | 233 | |
| 234 | 234 | # Is it a literal scalar? |
| 235 | | if ch == u'|' and not self.flow_level: |
| | 235 | if ch == '|' and not self.flow_level: |
| 236 | 236 | return self.fetch_literal() |
| 237 | 237 | |
| 238 | 238 | # Is it a folded scalar? |
| 239 | | if ch == u'>' and not self.flow_level: |
| | 239 | if ch == '>' and not self.flow_level: |
| 240 | 240 | return self.fetch_folded() |
| 241 | 241 | |
| 242 | 242 | # Is it a single quoted scalar? |
| 243 | | if ch == u'\'': |
| | 243 | if ch == '\'': |
| 244 | 244 | return self.fetch_single() |
| 245 | 245 | |
| 246 | 246 | # Is it a double quoted scalar? |
| 247 | | if ch == u'\"': |
| | 247 | if ch == '\"': |
| 248 | 248 | return self.fetch_double() |
| 249 | 249 | |
| 250 | 250 | # It must be a plain scalar then. |
| … |
… |
class Scanner(object): |
| 280 | 280 | # - should be no longer than 1024 characters. |
| 281 | 281 | # Disabling this procedure will allow simple keys of any length and |
| 282 | 282 | # height (may cause problems if indentation is broken though). |
| 283 | | for level in self.possible_simple_keys.keys(): |
| | 283 | for level in list(self.possible_simple_keys.keys()): |
| 284 | 284 | key = self.possible_simple_keys[level] |
| 285 | 285 | if key.line != self.line \ |
| 286 | 286 | or self.index-key.index > 1024: |
| … |
… |
class Scanner(object): |
| 691 | 691 | |
| 692 | 692 | # DOCUMENT-START: ^ '---' (' '|'\n') |
| 693 | 693 | if self.column == 0: |
| 694 | | if self.prefix(3) == u'---' \ |
| 695 | | and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': |
| | 694 | if self.prefix(3) == '---' \ |
| | 695 | and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': |
| 696 | 696 | return True |
| 697 | 697 | |
| 698 | 698 | def check_document_end(self): |
| 699 | 699 | |
| 700 | 700 | # DOCUMENT-END: ^ '...' (' '|'\n') |
| 701 | 701 | if self.column == 0: |
| 702 | | if self.prefix(3) == u'...' \ |
| 703 | | and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': |
| | 702 | if self.prefix(3) == '...' \ |
| | 703 | and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': |
| 704 | 704 | return True |
| 705 | 705 | |
| 706 | 706 | def check_block_entry(self): |
| 707 | 707 | |
| 708 | 708 | # BLOCK-ENTRY: '-' (' '|'\n') |
| 709 | | return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' |
| | 709 | return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' |
| 710 | 710 | |
| 711 | 711 | def check_key(self): |
| 712 | 712 | |
| … |
… |
class Scanner(object): |
| 716 | 716 | |
| 717 | 717 | # KEY(block context): '?' (' '|'\n') |
| 718 | 718 | else: |
| 719 | | return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' |
| | 719 | return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' |
| 720 | 720 | |
| 721 | 721 | def check_value(self): |
| 722 | 722 | |
| … |
… |
class Scanner(object): |
| 726 | 726 | |
| 727 | 727 | # VALUE(block context): ':' (' '|'\n') |
| 728 | 728 | else: |
| 729 | | return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' |
| | 729 | return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' |
| 730 | 730 | |
| 731 | 731 | def check_plain(self): |
| 732 | 732 | |
| … |
… |
class Scanner(object): |
| 743 | 743 | # '-' character) because we want the flow context to be space |
| 744 | 744 | # independent. |
| 745 | 745 | ch = self.peek() |
| 746 | | return ch not in u'\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`' \ |
| 747 | | or (self.peek(1) not in u'\0 \t\r\n\x85\u2028\u2029' |
| 748 | | and (ch == u'-' or (not self.flow_level and ch in u'?:'))) |
| | 746 | return ch not in '\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`' \ |
| | 747 | or (self.peek(1) not in '\0 \t\r\n\x85\u2028\u2029' |
| | 748 | and (ch == '-' or (not self.flow_level and ch in '?:'))) |
| 749 | 749 | |
| 750 | 750 | # Scanners. |
| 751 | 751 | |
| … |
… |
class Scanner(object): |
| 769 | 769 | # `unwind_indent` before issuing BLOCK-END. |
| 770 | 770 | # Scanners for block, flow, and plain scalars need to be modified. |
| 771 | 771 | |
| 772 | | if self.index == 0 and self.peek() == u'\uFEFF': |
| | 772 | if self.index == 0 and self.peek() == '\uFEFF': |
| 773 | 773 | self.forward() |
| 774 | 774 | found = False |
| 775 | 775 | while not found: |
| 776 | | while self.peek() == u' ': |
| | 776 | while self.peek() == ' ': |
| 777 | 777 | self.forward() |
| 778 | | if self.peek() == u'#': |
| 779 | | while self.peek() not in u'\0\r\n\x85\u2028\u2029': |
| | 778 | if self.peek() == '#': |
| | 779 | while self.peek() not in '\0\r\n\x85\u2028\u2029': |
| 780 | 780 | self.forward() |
| 781 | 781 | if self.scan_line_break(): |
| 782 | 782 | if not self.flow_level: |
| … |
… |
class Scanner(object): |
| 790 | 790 | self.forward() |
| 791 | 791 | name = self.scan_directive_name(start_mark) |
| 792 | 792 | value = None |
| 793 | | if name == u'YAML': |
| | 793 | if name == 'YAML': |
| 794 | 794 | value = self.scan_yaml_directive_value(start_mark) |
| 795 | 795 | end_mark = self.get_mark() |
| 796 | | elif name == u'TAG': |
| | 796 | elif name == 'TAG': |
| 797 | 797 | value = self.scan_tag_directive_value(start_mark) |
| 798 | 798 | end_mark = self.get_mark() |
| 799 | 799 | else: |
| 800 | 800 | end_mark = self.get_mark() |
| 801 | | while self.peek() not in u'\0\r\n\x85\u2028\u2029': |
| | 801 | while self.peek() not in '\0\r\n\x85\u2028\u2029': |
| 802 | 802 | self.forward() |
| 803 | 803 | self.scan_directive_ignored_line(start_mark) |
| 804 | 804 | return DirectiveToken(name, value, start_mark, end_mark) |
| … |
… |
class Scanner(object): |
| 807 | 807 | # See the specification for details. |
| 808 | 808 | length = 0 |
| 809 | 809 | ch = self.peek(length) |
| 810 | | while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 811 | | or ch in u'-_': |
| | 810 | while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 811 | or ch in '-_': |
| 812 | 812 | length += 1 |
| 813 | 813 | ch = self.peek(length) |
| 814 | 814 | if not length: |
| … |
… |
class Scanner(object): |
| 818 | 818 | value = self.prefix(length) |
| 819 | 819 | self.forward(length) |
| 820 | 820 | ch = self.peek() |
| 821 | | if ch not in u'\0 \r\n\x85\u2028\u2029': |
| | 821 | if ch not in '\0 \r\n\x85\u2028\u2029': |
| 822 | 822 | raise ScannerError("while scanning a directive", start_mark, |
| 823 | 823 | "expected alphabetic or numeric character, but found %r" |
| 824 | 824 | % ch.encode('utf-8'), self.get_mark()) |
| … |
… |
class Scanner(object): |
| 826 | 826 | |
| 827 | 827 | def scan_yaml_directive_value(self, start_mark): |
| 828 | 828 | # See the specification for details. |
| 829 | | while self.peek() == u' ': |
| | 829 | while self.peek() == ' ': |
| 830 | 830 | self.forward() |
| 831 | 831 | major = self.scan_yaml_directive_number(start_mark) |
| 832 | 832 | if self.peek() != '.': |
| … |
… |
class Scanner(object): |
| 836 | 836 | self.get_mark()) |
| 837 | 837 | self.forward() |
| 838 | 838 | minor = self.scan_yaml_directive_number(start_mark) |
| 839 | | if self.peek() not in u'\0 \r\n\x85\u2028\u2029': |
| | 839 | if self.peek() not in '\0 \r\n\x85\u2028\u2029': |
| 840 | 840 | raise ScannerError("while scanning a directive", start_mark, |
| 841 | 841 | "expected a digit or ' ', but found %r" |
| 842 | 842 | % self.peek().encode('utf-8'), |
| … |
… |
class Scanner(object): |
| 846 | 846 | def scan_yaml_directive_number(self, start_mark): |
| 847 | 847 | # See the specification for details. |
| 848 | 848 | ch = self.peek() |
| 849 | | if not (u'0' <= ch <= '9'): |
| | 849 | if not ('0' <= ch <= '9'): |
| 850 | 850 | raise ScannerError("while scanning a directive", start_mark, |
| 851 | 851 | "expected a digit, but found %r" % ch.encode('utf-8'), |
| 852 | 852 | self.get_mark()) |
| 853 | 853 | length = 0 |
| 854 | | while u'0' <= self.peek(length) <= u'9': |
| | 854 | while '0' <= self.peek(length) <= '9': |
| 855 | 855 | length += 1 |
| 856 | 856 | value = int(self.prefix(length)) |
| 857 | 857 | self.forward(length) |
| … |
… |
class Scanner(object): |
| 859 | 859 | |
| 860 | 860 | def scan_tag_directive_value(self, start_mark): |
| 861 | 861 | # See the specification for details. |
| 862 | | while self.peek() == u' ': |
| | 862 | while self.peek() == ' ': |
| 863 | 863 | self.forward() |
| 864 | 864 | handle = self.scan_tag_directive_handle(start_mark) |
| 865 | | while self.peek() == u' ': |
| | 865 | while self.peek() == ' ': |
| 866 | 866 | self.forward() |
| 867 | 867 | prefix = self.scan_tag_directive_prefix(start_mark) |
| 868 | 868 | return (handle, prefix) |
| … |
… |
class Scanner(object): |
| 871 | 871 | # See the specification for details. |
| 872 | 872 | value = self.scan_tag_handle('directive', start_mark) |
| 873 | 873 | ch = self.peek() |
| 874 | | if ch != u' ': |
| | 874 | if ch != ' ': |
| 875 | 875 | raise ScannerError("while scanning a directive", start_mark, |
| 876 | 876 | "expected ' ', but found %r" % ch.encode('utf-8'), |
| 877 | 877 | self.get_mark()) |
| … |
… |
class Scanner(object): |
| 881 | 881 | # See the specification for details. |
| 882 | 882 | value = self.scan_tag_uri('directive', start_mark) |
| 883 | 883 | ch = self.peek() |
| 884 | | if ch not in u'\0 \r\n\x85\u2028\u2029': |
| | 884 | if ch not in '\0 \r\n\x85\u2028\u2029': |
| 885 | 885 | raise ScannerError("while scanning a directive", start_mark, |
| 886 | 886 | "expected ' ', but found %r" % ch.encode('utf-8'), |
| 887 | 887 | self.get_mark()) |
| … |
… |
class Scanner(object): |
| 889 | 889 | |
| 890 | 890 | def scan_directive_ignored_line(self, start_mark): |
| 891 | 891 | # See the specification for details. |
| 892 | | while self.peek() == u' ': |
| | 892 | while self.peek() == ' ': |
| 893 | 893 | self.forward() |
| 894 | | if self.peek() == u'#': |
| 895 | | while self.peek() not in u'\0\r\n\x85\u2028\u2029': |
| | 894 | if self.peek() == '#': |
| | 895 | while self.peek() not in '\0\r\n\x85\u2028\u2029': |
| 896 | 896 | self.forward() |
| 897 | 897 | ch = self.peek() |
| 898 | | if ch not in u'\0\r\n\x85\u2028\u2029': |
| | 898 | if ch not in '\0\r\n\x85\u2028\u2029': |
| 899 | 899 | raise ScannerError("while scanning a directive", start_mark, |
| 900 | 900 | "expected a comment or a line break, but found %r" |
| 901 | 901 | % ch.encode('utf-8'), self.get_mark()) |
| … |
… |
class Scanner(object): |
| 919 | 919 | self.forward() |
| 920 | 920 | length = 0 |
| 921 | 921 | ch = self.peek(length) |
| 922 | | while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 923 | | or ch in u'-_': |
| | 922 | while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 923 | or ch in '-_': |
| 924 | 924 | length += 1 |
| 925 | 925 | ch = self.peek(length) |
| 926 | 926 | if not length: |
| … |
… |
class Scanner(object): |
| 930 | 930 | value = self.prefix(length) |
| 931 | 931 | self.forward(length) |
| 932 | 932 | ch = self.peek() |
| 933 | | if ch not in u'\0 \t\r\n\x85\u2028\u2029?:,]}%@`': |
| | 933 | if ch not in '\0 \t\r\n\x85\u2028\u2029?:,]}%@`': |
| 934 | 934 | raise ScannerError("while scanning an %s" % name, start_mark, |
| 935 | 935 | "expected alphabetic or numeric character, but found %r" |
| 936 | 936 | % ch.encode('utf-8'), self.get_mark()) |
| … |
… |
class Scanner(object): |
| 941 | 941 | # See the specification for details. |
| 942 | 942 | start_mark = self.get_mark() |
| 943 | 943 | ch = self.peek(1) |
| 944 | | if ch == u'<': |
| | 944 | if ch == '<': |
| 945 | 945 | handle = None |
| 946 | 946 | self.forward(2) |
| 947 | 947 | suffix = self.scan_tag_uri('tag', start_mark) |
| 948 | | if self.peek() != u'>': |
| | 948 | if self.peek() != '>': |
| 949 | 949 | raise ScannerError("while parsing a tag", start_mark, |
| 950 | 950 | "expected '>', but found %r" % self.peek().encode('utf-8'), |
| 951 | 951 | self.get_mark()) |
| 952 | 952 | self.forward() |
| 953 | | elif ch in u'\0 \t\r\n\x85\u2028\u2029': |
| | 953 | elif ch in '\0 \t\r\n\x85\u2028\u2029': |
| 954 | 954 | handle = None |
| 955 | | suffix = u'!' |
| | 955 | suffix = '!' |
| 956 | 956 | self.forward() |
| 957 | 957 | else: |
| 958 | 958 | length = 1 |
| 959 | 959 | use_handle = False |
| 960 | | while ch not in u'\0 \r\n\x85\u2028\u2029': |
| 961 | | if ch == u'!': |
| | 960 | while ch not in '\0 \r\n\x85\u2028\u2029': |
| | 961 | if ch == '!': |
| 962 | 962 | use_handle = True |
| 963 | 963 | break |
| 964 | 964 | length += 1 |
| 965 | 965 | ch = self.peek(length) |
| 966 | | handle = u'!' |
| | 966 | handle = '!' |
| 967 | 967 | if use_handle: |
| 968 | 968 | handle = self.scan_tag_handle('tag', start_mark) |
| 969 | 969 | else: |
| 970 | | handle = u'!' |
| | 970 | handle = '!' |
| 971 | 971 | self.forward() |
| 972 | 972 | suffix = self.scan_tag_uri('tag', start_mark) |
| 973 | 973 | ch = self.peek() |
| 974 | | if ch not in u'\0 \r\n\x85\u2028\u2029': |
| | 974 | if ch not in '\0 \r\n\x85\u2028\u2029': |
| 975 | 975 | raise ScannerError("while scanning a tag", start_mark, |
| 976 | 976 | "expected ' ', but found %r" % ch.encode('utf-8'), |
| 977 | 977 | self.get_mark()) |
| … |
… |
class Scanner(object): |
| 1005 | 1005 | else: |
| 1006 | 1006 | indent = min_indent+increment-1 |
| 1007 | 1007 | breaks, end_mark = self.scan_block_scalar_breaks(indent) |
| 1008 | | line_break = u'' |
| | 1008 | line_break = '' |
| 1009 | 1009 | |
| 1010 | 1010 | # Scan the inner part of the block scalar. |
| 1011 | | while self.column == indent and self.peek() != u'\0': |
| | 1011 | while self.column == indent and self.peek() != '\0': |
| 1012 | 1012 | chunks.extend(breaks) |
| 1013 | | leading_non_space = self.peek() not in u' \t' |
| | 1013 | leading_non_space = self.peek() not in ' \t' |
| 1014 | 1014 | length = 0 |
| 1015 | | while self.peek(length) not in u'\0\r\n\x85\u2028\u2029': |
| | 1015 | while self.peek(length) not in '\0\r\n\x85\u2028\u2029': |
| 1016 | 1016 | length += 1 |
| 1017 | 1017 | chunks.append(self.prefix(length)) |
| 1018 | 1018 | self.forward(length) |
| 1019 | 1019 | line_break = self.scan_line_break() |
| 1020 | 1020 | breaks, end_mark = self.scan_block_scalar_breaks(indent) |
| 1021 | | if self.column == indent and self.peek() != u'\0': |
| | 1021 | if self.column == indent and self.peek() != '\0': |
| 1022 | 1022 | |
| 1023 | 1023 | # Unfortunately, folding rules are ambiguous. |
| 1024 | 1024 | # |
| 1025 | 1025 | # This is the folding according to the specification: |
| 1026 | 1026 | |
| 1027 | | if folded and line_break == u'\n' \ |
| 1028 | | and leading_non_space and self.peek() not in u' \t': |
| | 1027 | if folded and line_break == '\n' \ |
| | 1028 | and leading_non_space and self.peek() not in ' \t': |
| 1029 | 1029 | if not breaks: |
| 1030 | | chunks.append(u' ') |
| | 1030 | chunks.append(' ') |
| 1031 | 1031 | else: |
| 1032 | 1032 | chunks.append(line_break) |
| 1033 | 1033 | |
| 1034 | 1034 | # This is Clark Evans's interpretation (also in the spec |
| 1035 | 1035 | # examples): |
| 1036 | 1036 | # |
| 1037 | | #if folded and line_break == u'\n': |
| | 1037 | #if folded and line_break == '\n': |
| 1038 | 1038 | # if not breaks: |
| 1039 | 1039 | # if self.peek() not in ' \t': |
| 1040 | | # chunks.append(u' ') |
| | 1040 | # chunks.append(' ') |
| 1041 | 1041 | # else: |
| 1042 | 1042 | # chunks.append(line_break) |
| 1043 | 1043 | #else: |
| … |
… |
class Scanner(object): |
| 1052 | 1052 | chunks.extend(breaks) |
| 1053 | 1053 | |
| 1054 | 1054 | # We are done. |
| 1055 | | return ScalarToken(u''.join(chunks), False, start_mark, end_mark, |
| | 1055 | return ScalarToken(''.join(chunks), False, start_mark, end_mark, |
| 1056 | 1056 | style) |
| 1057 | 1057 | |
| 1058 | 1058 | def scan_block_scalar_indicators(self, start_mark): |
| … |
… |
class Scanner(object): |
| 1060 | 1060 | chomping = None |
| 1061 | 1061 | increment = None |
| 1062 | 1062 | ch = self.peek() |
| 1063 | | if ch in u'+-': |
| | 1063 | if ch in '+-': |
| 1064 | 1064 | if ch == '+': |
| 1065 | 1065 | chomping = True |
| 1066 | 1066 | else: |
| 1067 | 1067 | chomping = False |
| 1068 | 1068 | self.forward() |
| 1069 | 1069 | ch = self.peek() |
| 1070 | | if ch in u'0123456789': |
| | 1070 | if ch in '0123456789': |
| 1071 | 1071 | increment = int(ch) |
| 1072 | 1072 | if increment == 0: |
| 1073 | 1073 | raise ScannerError("while scanning a block scalar", start_mark, |
| 1074 | 1074 | "expected indentation indicator in the range 1-9, but found 0", |
| 1075 | 1075 | self.get_mark()) |
| 1076 | 1076 | self.forward() |
| 1077 | | elif ch in u'0123456789': |
| | 1077 | elif ch in '0123456789': |
| 1078 | 1078 | increment = int(ch) |
| 1079 | 1079 | if increment == 0: |
| 1080 | 1080 | raise ScannerError("while scanning a block scalar", start_mark, |
| … |
… |
class Scanner(object): |
| 1082 | 1082 | self.get_mark()) |
| 1083 | 1083 | self.forward() |
| 1084 | 1084 | ch = self.peek() |
| 1085 | | if ch in u'+-': |
| | 1085 | if ch in '+-': |
| 1086 | 1086 | if ch == '+': |
| 1087 | 1087 | chomping = True |
| 1088 | 1088 | else: |
| 1089 | 1089 | chomping = False |
| 1090 | 1090 | self.forward() |
| 1091 | 1091 | ch = self.peek() |
| 1092 | | if ch not in u'\0 \r\n\x85\u2028\u2029': |
| | 1092 | if ch not in '\0 \r\n\x85\u2028\u2029': |
| 1093 | 1093 | raise ScannerError("while scanning a block scalar", start_mark, |
| 1094 | 1094 | "expected chomping or indentation indicators, but found %r" |
| 1095 | 1095 | % ch.encode('utf-8'), self.get_mark()) |
| … |
… |
class Scanner(object): |
| 1097 | 1097 | |
| 1098 | 1098 | def scan_block_scalar_ignored_line(self, start_mark): |
| 1099 | 1099 | # See the specification for details. |
| 1100 | | while self.peek() == u' ': |
| | 1100 | while self.peek() == ' ': |
| 1101 | 1101 | self.forward() |
| 1102 | | if self.peek() == u'#': |
| 1103 | | while self.peek() not in u'\0\r\n\x85\u2028\u2029': |
| | 1102 | if self.peek() == '#': |
| | 1103 | while self.peek() not in '\0\r\n\x85\u2028\u2029': |
| 1104 | 1104 | self.forward() |
| 1105 | 1105 | ch = self.peek() |
| 1106 | | if ch not in u'\0\r\n\x85\u2028\u2029': |
| | 1106 | if ch not in '\0\r\n\x85\u2028\u2029': |
| 1107 | 1107 | raise ScannerError("while scanning a block scalar", start_mark, |
| 1108 | 1108 | "expected a comment or a line break, but found %r" |
| 1109 | 1109 | % ch.encode('utf-8'), self.get_mark()) |
| … |
… |
class Scanner(object): |
| 1114 | 1114 | chunks = [] |
| 1115 | 1115 | max_indent = 0 |
| 1116 | 1116 | end_mark = self.get_mark() |
| 1117 | | while self.peek() in u' \r\n\x85\u2028\u2029': |
| 1118 | | if self.peek() != u' ': |
| | 1117 | while self.peek() in ' \r\n\x85\u2028\u2029': |
| | 1118 | if self.peek() != ' ': |
| 1119 | 1119 | chunks.append(self.scan_line_break()) |
| 1120 | 1120 | end_mark = self.get_mark() |
| 1121 | 1121 | else: |
| … |
… |
class Scanner(object): |
| 1128 | 1128 | # See the specification for details. |
| 1129 | 1129 | chunks = [] |
| 1130 | 1130 | end_mark = self.get_mark() |
| 1131 | | while self.column < indent and self.peek() == u' ': |
| | 1131 | while self.column < indent and self.peek() == ' ': |
| 1132 | 1132 | self.forward() |
| 1133 | | while self.peek() in u'\r\n\x85\u2028\u2029': |
| | 1133 | while self.peek() in '\r\n\x85\u2028\u2029': |
| 1134 | 1134 | chunks.append(self.scan_line_break()) |
| 1135 | 1135 | end_mark = self.get_mark() |
| 1136 | | while self.column < indent and self.peek() == u' ': |
| | 1136 | while self.column < indent and self.peek() == ' ': |
| 1137 | 1137 | self.forward() |
| 1138 | 1138 | return chunks, end_mark |
| 1139 | 1139 | |
| … |
… |
class Scanner(object): |
| 1158 | 1158 | chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) |
| 1159 | 1159 | self.forward() |
| 1160 | 1160 | end_mark = self.get_mark() |
| 1161 | | return ScalarToken(u''.join(chunks), False, start_mark, end_mark, |
| | 1161 | return ScalarToken(''.join(chunks), False, start_mark, end_mark, |
| 1162 | 1162 | style) |
| 1163 | 1163 | |
| 1164 | 1164 | ESCAPE_REPLACEMENTS = { |
| 1165 | | u'0': u'\0', |
| 1166 | | u'a': u'\x07', |
| 1167 | | u'b': u'\x08', |
| 1168 | | u't': u'\x09', |
| 1169 | | u'\t': u'\x09', |
| 1170 | | u'n': u'\x0A', |
| 1171 | | u'v': u'\x0B', |
| 1172 | | u'f': u'\x0C', |
| 1173 | | u'r': u'\x0D', |
| 1174 | | u'e': u'\x1B', |
| 1175 | | u' ': u'\x20', |
| 1176 | | u'\"': u'\"', |
| 1177 | | u'\\': u'\\', |
| 1178 | | u'N': u'\x85', |
| 1179 | | u'_': u'\xA0', |
| 1180 | | u'L': u'\u2028', |
| 1181 | | u'P': u'\u2029', |
| | 1165 | '0': '\0', |
| | 1166 | 'a': '\x07', |
| | 1167 | 'b': '\x08', |
| | 1168 | 't': '\x09', |
| | 1169 | '\t': '\x09', |
| | 1170 | 'n': '\x0A', |
| | 1171 | 'v': '\x0B', |
| | 1172 | 'f': '\x0C', |
| | 1173 | 'r': '\x0D', |
| | 1174 | 'e': '\x1B', |
| | 1175 | ' ': '\x20', |
| | 1176 | '\"': '\"', |
| | 1177 | '\\': '\\', |
| | 1178 | 'N': '\x85', |
| | 1179 | '_': '\xA0', |
| | 1180 | 'L': '\u2028', |
| | 1181 | 'P': '\u2029', |
| 1182 | 1182 | } |
| 1183 | 1183 | |
| 1184 | 1184 | ESCAPE_CODES = { |
| 1185 | | u'x': 2, |
| 1186 | | u'u': 4, |
| 1187 | | u'U': 8, |
| | 1185 | 'x': 2, |
| | 1186 | 'u': 4, |
| | 1187 | 'U': 8, |
| 1188 | 1188 | } |
| 1189 | 1189 | |
| 1190 | 1190 | def scan_flow_scalar_non_spaces(self, double, start_mark): |
| … |
… |
class Scanner(object): |
| 1192 | 1192 | chunks = [] |
| 1193 | 1193 | while True: |
| 1194 | 1194 | length = 0 |
| 1195 | | while self.peek(length) not in u'\'\"\\\0 \t\r\n\x85\u2028\u2029': |
| | 1195 | while self.peek(length) not in '\'\"\\\0 \t\r\n\x85\u2028\u2029': |
| 1196 | 1196 | length += 1 |
| 1197 | 1197 | if length: |
| 1198 | 1198 | chunks.append(self.prefix(length)) |
| 1199 | 1199 | self.forward(length) |
| 1200 | 1200 | ch = self.peek() |
| 1201 | | if not double and ch == u'\'' and self.peek(1) == u'\'': |
| 1202 | | chunks.append(u'\'') |
| | 1201 | if not double and ch == '\'' and self.peek(1) == '\'': |
| | 1202 | chunks.append('\'') |
| 1203 | 1203 | self.forward(2) |
| 1204 | | elif (double and ch == u'\'') or (not double and ch in u'\"\\'): |
| | 1204 | elif (double and ch == '\'') or (not double and ch in '\"\\'): |
| 1205 | 1205 | chunks.append(ch) |
| 1206 | 1206 | self.forward() |
| 1207 | | elif double and ch == u'\\': |
| | 1207 | elif double and ch == '\\': |
| 1208 | 1208 | self.forward() |
| 1209 | 1209 | ch = self.peek() |
| 1210 | 1210 | if ch in self.ESCAPE_REPLACEMENTS: |
| … |
… |
class Scanner(object): |
| 1214 | 1214 | length = self.ESCAPE_CODES[ch] |
| 1215 | 1215 | self.forward() |
| 1216 | 1216 | for k in range(length): |
| 1217 | | if self.peek(k) not in u'0123456789ABCDEFabcdef': |
| | 1217 | if self.peek(k) not in '0123456789ABCDEFabcdef': |
| 1218 | 1218 | raise ScannerError("while scanning a double-quoted scalar", start_mark, |
| 1219 | 1219 | "expected escape sequence of %d hexdecimal numbers, but found %r" % |
| 1220 | 1220 | (length, self.peek(k).encode('utf-8')), self.get_mark()) |
| 1221 | 1221 | code = int(self.prefix(length), 16) |
| 1222 | | chunks.append(unichr(code)) |
| | 1222 | chunks.append(chr(code)) |
| 1223 | 1223 | self.forward(length) |
| 1224 | | elif ch in u'\r\n\x85\u2028\u2029': |
| | 1224 | elif ch in '\r\n\x85\u2028\u2029': |
| 1225 | 1225 | self.scan_line_break() |
| 1226 | 1226 | chunks.extend(self.scan_flow_scalar_breaks(double, start_mark)) |
| 1227 | 1227 | else: |
| … |
… |
class Scanner(object): |
| 1234 | 1234 | # See the specification for details. |
| 1235 | 1235 | chunks = [] |
| 1236 | 1236 | length = 0 |
| 1237 | | while self.peek(length) in u' \t': |
| | 1237 | while self.peek(length) in ' \t': |
| 1238 | 1238 | length += 1 |
| 1239 | 1239 | whitespaces = self.prefix(length) |
| 1240 | 1240 | self.forward(length) |
| 1241 | 1241 | ch = self.peek() |
| 1242 | | if ch == u'\0': |
| | 1242 | if ch == '\0': |
| 1243 | 1243 | raise ScannerError("while scanning a quoted scalar", start_mark, |
| 1244 | 1244 | "found unexpected end of stream", self.get_mark()) |
| 1245 | | elif ch in u'\r\n\x85\u2028\u2029': |
| | 1245 | elif ch in '\r\n\x85\u2028\u2029': |
| 1246 | 1246 | line_break = self.scan_line_break() |
| 1247 | 1247 | breaks = self.scan_flow_scalar_breaks(double, start_mark) |
| 1248 | | if line_break != u'\n': |
| | 1248 | if line_break != '\n': |
| 1249 | 1249 | chunks.append(line_break) |
| 1250 | 1250 | elif not breaks: |
| 1251 | | chunks.append(u' ') |
| | 1251 | chunks.append(' ') |
| 1252 | 1252 | chunks.extend(breaks) |
| 1253 | 1253 | else: |
| 1254 | 1254 | chunks.append(whitespaces) |
| … |
… |
class Scanner(object): |
| 1261 | 1261 | # Instead of checking indentation, we check for document |
| 1262 | 1262 | # separators. |
| 1263 | 1263 | prefix = self.prefix(3) |
| 1264 | | if (prefix == u'---' or prefix == u'...') \ |
| 1265 | | and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': |
| | 1264 | if (prefix == '---' or prefix == '...') \ |
| | 1265 | and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': |
| 1266 | 1266 | raise ScannerError("while scanning a quoted scalar", start_mark, |
| 1267 | 1267 | "found unexpected document separator", self.get_mark()) |
| 1268 | | while self.peek() in u' \t': |
| | 1268 | while self.peek() in ' \t': |
| 1269 | 1269 | self.forward() |
| 1270 | | if self.peek() in u'\r\n\x85\u2028\u2029': |
| | 1270 | if self.peek() in '\r\n\x85\u2028\u2029': |
| 1271 | 1271 | chunks.append(self.scan_line_break()) |
| 1272 | 1272 | else: |
| 1273 | 1273 | return chunks |
| … |
… |
class Scanner(object): |
| 1289 | 1289 | spaces = [] |
| 1290 | 1290 | while True: |
| 1291 | 1291 | length = 0 |
| 1292 | | if self.peek() == u'#': |
| | 1292 | if self.peek() == '#': |
| 1293 | 1293 | break |
| 1294 | 1294 | while True: |
| 1295 | 1295 | ch = self.peek(length) |
| 1296 | | if ch in u'\0 \t\r\n\x85\u2028\u2029' \ |
| 1297 | | or (not self.flow_level and ch == u':' and |
| 1298 | | self.peek(length+1) in u'\0 \t\r\n\x85\u2028\u2029') \ |
| 1299 | | or (self.flow_level and ch in u',:?[]{}'): |
| | 1296 | if ch in '\0 \t\r\n\x85\u2028\u2029' \ |
| | 1297 | or (not self.flow_level and ch == ':' and |
| | 1298 | self.peek(length+1) in '\0 \t\r\n\x85\u2028\u2029') \ |
| | 1299 | or (self.flow_level and ch in ',:?[]{}'): |
| 1300 | 1300 | break |
| 1301 | 1301 | length += 1 |
| 1302 | 1302 | # It's not clear what we should do with ':' in the flow context. |
| 1303 | | if (self.flow_level and ch == u':' |
| 1304 | | and self.peek(length+1) not in u'\0 \t\r\n\x85\u2028\u2029,[]{}'): |
| | 1303 | if (self.flow_level and ch == ':' |
| | 1304 | and self.peek(length+1) not in '\0 \t\r\n\x85\u2028\u2029,[]{}'): |
| 1305 | 1305 | self.forward(length) |
| 1306 | 1306 | raise ScannerError("while scanning a plain scalar", start_mark, |
| 1307 | 1307 | "found unexpected ':'", self.get_mark(), |
| … |
… |
class Scanner(object): |
| 1314 | 1314 | self.forward(length) |
| 1315 | 1315 | end_mark = self.get_mark() |
| 1316 | 1316 | spaces = self.scan_plain_spaces(indent, start_mark) |
| 1317 | | if not spaces or self.peek() == u'#' \ |
| | 1317 | if not spaces or self.peek() == '#' \ |
| 1318 | 1318 | or (not self.flow_level and self.column < indent): |
| 1319 | 1319 | break |
| 1320 | | return ScalarToken(u''.join(chunks), True, start_mark, end_mark) |
| | 1320 | return ScalarToken(''.join(chunks), True, start_mark, end_mark) |
| 1321 | 1321 | |
| 1322 | 1322 | def scan_plain_spaces(self, indent, start_mark): |
| 1323 | 1323 | # See the specification for details. |
| … |
… |
class Scanner(object): |
| 1325 | 1325 | # We just forbid them completely. Do not use tabs in YAML! |
| 1326 | 1326 | chunks = [] |
| 1327 | 1327 | length = 0 |
| 1328 | | while self.peek(length) in u' ': |
| | 1328 | while self.peek(length) in ' ': |
| 1329 | 1329 | length += 1 |
| 1330 | 1330 | whitespaces = self.prefix(length) |
| 1331 | 1331 | self.forward(length) |
| 1332 | 1332 | ch = self.peek() |
| 1333 | | if ch in u'\r\n\x85\u2028\u2029': |
| | 1333 | if ch in '\r\n\x85\u2028\u2029': |
| 1334 | 1334 | line_break = self.scan_line_break() |
| 1335 | 1335 | self.allow_simple_key = True |
| 1336 | 1336 | prefix = self.prefix(3) |
| 1337 | | if (prefix == u'---' or prefix == u'...') \ |
| 1338 | | and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': |
| | 1337 | if (prefix == '---' or prefix == '...') \ |
| | 1338 | and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': |
| 1339 | 1339 | return |
| 1340 | 1340 | breaks = [] |
| 1341 | | while self.peek() in u' \r\n\x85\u2028\u2029': |
| | 1341 | while self.peek() in ' \r\n\x85\u2028\u2029': |
| 1342 | 1342 | if self.peek() == ' ': |
| 1343 | 1343 | self.forward() |
| 1344 | 1344 | else: |
| 1345 | 1345 | breaks.append(self.scan_line_break()) |
| 1346 | 1346 | prefix = self.prefix(3) |
| 1347 | | if (prefix == u'---' or prefix == u'...') \ |
| 1348 | | and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': |
| | 1347 | if (prefix == '---' or prefix == '...') \ |
| | 1348 | and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': |
| 1349 | 1349 | return |
| 1350 | | if line_break != u'\n': |
| | 1350 | if line_break != '\n': |
| 1351 | 1351 | chunks.append(line_break) |
| 1352 | 1352 | elif not breaks: |
| 1353 | | chunks.append(u' ') |
| | 1353 | chunks.append(' ') |
| 1354 | 1354 | chunks.extend(breaks) |
| 1355 | 1355 | elif whitespaces: |
| 1356 | 1356 | chunks.append(whitespaces) |
| … |
… |
class Scanner(object): |
| 1361 | 1361 | # For some strange reasons, the specification does not allow '_' in |
| 1362 | 1362 | # tag handles. I have allowed it anyway. |
| 1363 | 1363 | ch = self.peek() |
| 1364 | | if ch != u'!': |
| | 1364 | if ch != '!': |
| 1365 | 1365 | raise ScannerError("while scanning a %s" % name, start_mark, |
| 1366 | 1366 | "expected '!', but found %r" % ch.encode('utf-8'), |
| 1367 | 1367 | self.get_mark()) |
| 1368 | 1368 | length = 1 |
| 1369 | 1369 | ch = self.peek(length) |
| 1370 | | if ch != u' ': |
| 1371 | | while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 1372 | | or ch in u'-_': |
| | 1370 | if ch != ' ': |
| | 1371 | while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 1372 | or ch in '-_': |
| 1373 | 1373 | length += 1 |
| 1374 | 1374 | ch = self.peek(length) |
| 1375 | | if ch != u'!': |
| | 1375 | if ch != '!': |
| 1376 | 1376 | self.forward(length) |
| 1377 | 1377 | raise ScannerError("while scanning a %s" % name, start_mark, |
| 1378 | 1378 | "expected '!', but found %r" % ch.encode('utf-8'), |
| … |
… |
class Scanner(object): |
| 1388 | 1388 | chunks = [] |
| 1389 | 1389 | length = 0 |
| 1390 | 1390 | ch = self.peek(length) |
| 1391 | | while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ |
| 1392 | | or ch in u'-;/?:@&=+$,_.!~*\'()[]%': |
| 1393 | | if ch == u'%': |
| | 1391 | while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ |
| | 1392 | or ch in '-;/?:@&=+$,_.!~*\'()[]%': |
| | 1393 | if ch == '%': |
| 1394 | 1394 | chunks.append(self.prefix(length)) |
| 1395 | 1395 | self.forward(length) |
| 1396 | 1396 | length = 0 |
| … |
… |
class Scanner(object): |
| 1406 | 1406 | raise ScannerError("while parsing a %s" % name, start_mark, |
| 1407 | 1407 | "expected URI, but found %r" % ch.encode('utf-8'), |
| 1408 | 1408 | self.get_mark()) |
| 1409 | | return u''.join(chunks) |
| | 1409 | return ''.join(chunks) |
| 1410 | 1410 | |
| 1411 | 1411 | def scan_uri_escapes(self, name, start_mark): |
| 1412 | 1412 | # See the specification for details. |
| 1413 | 1413 | bytes = [] |
| 1414 | 1414 | mark = self.get_mark() |
| 1415 | | while self.peek() == u'%': |
| | 1415 | while self.peek() == '%': |
| 1416 | 1416 | self.forward() |
| 1417 | 1417 | for k in range(2): |
| 1418 | | if self.peek(k) not in u'0123456789ABCDEFabcdef': |
| | 1418 | if self.peek(k) not in '0123456789ABCDEFabcdef': |
| 1419 | 1419 | raise ScannerError("while scanning a %s" % name, start_mark, |
| 1420 | 1420 | "expected URI escape sequence of 2 hexdecimal numbers, but found %r" % |
| 1421 | 1421 | (self.peek(k).encode('utf-8')), self.get_mark()) |
| 1422 | 1422 | bytes.append(chr(int(self.prefix(2), 16))) |
| 1423 | 1423 | self.forward(2) |
| 1424 | 1424 | try: |
| 1425 | | value = unicode(''.join(bytes), 'utf-8') |
| 1426 | | except UnicodeDecodeError, exc: |
| | 1425 | value = str(''.join(bytes)) |
| | 1426 | except UnicodeDecodeError as exc: |
| 1427 | 1427 | raise ScannerError("while scanning a %s" % name, start_mark, str(exc), mark) |
| 1428 | 1428 | return value |
| 1429 | 1429 | |
| … |
… |
class Scanner(object): |
| 1437 | 1437 | # '\u2029 : '\u2029' |
| 1438 | 1438 | # default : '' |
| 1439 | 1439 | ch = self.peek() |
| 1440 | | if ch in u'\r\n\x85': |
| 1441 | | if self.prefix(2) == u'\r\n': |
| | 1440 | if ch in '\r\n\x85': |
| | 1441 | if self.prefix(2) == '\r\n': |
| 1442 | 1442 | self.forward(2) |
| 1443 | 1443 | else: |
| 1444 | 1444 | self.forward() |
| 1445 | | return u'\n' |
| 1446 | | elif ch in u'\u2028\u2029': |
| | 1445 | return '\n' |
| | 1446 | elif ch in '\u2028\u2029': |
| 1447 | 1447 | self.forward() |
| 1448 | 1448 | return ch |
| 1449 | | return u'' |
| | 1449 | return '' |
| 1450 | 1450 | |
| 1451 | 1451 | #try: |
| 1452 | 1452 | # import psyco |
-
diff --git lib/yaml/serializer.py lib/yaml/serializer.py
index 2101f95..d193c41 100644
|
|
|
|
| 1 | 1 | |
| 2 | 2 | __all__ = ['Serializer', 'SerializerError'] |
| 3 | 3 | |
| 4 | | from error import YAMLError |
| 5 | | from events import * |
| 6 | | from nodes import * |
| | 4 | from yaml.error import YAMLError |
| | 5 | from yaml.events import * |
| | 6 | from yaml.nodes import * |
| 7 | 7 | |
| 8 | 8 | class SerializerError(YAMLError): |
| 9 | 9 | pass |
| 10 | 10 | |
| 11 | | class Serializer(object): |
| | 11 | class Serializer: |
| 12 | 12 | |
| 13 | | ANCHOR_TEMPLATE = u'id%03d' |
| | 13 | ANCHOR_TEMPLATE = 'id%03d' |
| 14 | 14 | |
| 15 | 15 | def __init__(self, encoding=None, |
| 16 | 16 | explicit_start=None, explicit_end=None, version=None, tags=None): |
-
diff --git lib/yaml/tokens.py lib/yaml/tokens.py
index 4d0b48a..0cbd7e5 100644
|
|
|
|
| 1 | 1 | |
| 2 | | class Token(object): |
| | 2 | class Token: |
| 3 | 3 | def __init__(self, start_mark, end_mark): |
| 4 | 4 | self.start_mark = start_mark |
| 5 | 5 | self.end_mark = end_mark |
| 6 | 6 | def __repr__(self): |
| 7 | | attributes = [key for key in self.__dict__ |
| 8 | | if not key.endswith('_mark')] |
| 9 | | attributes.sort() |
| 10 | | arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) |
| 11 | | for key in attributes]) |
| | 7 | attributes = sorted(key for key in self.__dict__ |
| | 8 | if not key.endswith('_mark')) |
| | 9 | arguments = ', '.join('%s=%r' % (key, getattr(self, key)) |
| | 10 | for key in attributes) |
| 12 | 11 | return '%s(%s)' % (self.__class__.__name__, arguments) |
| 13 | 12 | |
| 14 | 13 | #class BOMToken(Token): |
-
diff --git tests/data/construct-binary.code tests/data/construct-binary.code
index 67ac0d5..30bfc3f 100644
|
|
|
|
| 1 | 1 | { |
| 2 | 2 | "canonical": |
| 3 | | "GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", |
| | 3 | b"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", |
| 4 | 4 | "generic": |
| 5 | | "GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", |
| | 5 | b"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", |
| 6 | 6 | "description": "The binary value above is a tiny arrow encoded as a gif image.", |
| 7 | 7 | } |
-
diff --git tests/data/construct-python-bytes-ascii.code tests/data/construct-python-bytes-ascii.code
new file mode 100644
index 0000000..aa9a80b
-
diff --git tests/data/construct-python-bytes-ascii.data tests/data/construct-python-bytes-ascii.data
new file mode 100644
index 0000000..dc53f06
|
-
|
+
|
|
| | 1 | --- !!python/bytes "ascii string" |
-
diff --git tests/data/construct-python-bytes-utf8.code tests/data/construct-python-bytes-utf8.code
new file mode 100644
index 0000000..6ca7d8f
|
-
|
+
|
|
| | 1 | '\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430'.encode('utf-8') |
-
diff --git tests/data/construct-python-bytes-utf8.data tests/data/construct-python-bytes-utf8.data
new file mode 100644
index 0000000..4e916c0
|
-
|
+
|
|
| | 1 | --- !!python/bytes "ÐÑП ÑÐœÐžÐºÐŸÐŽÐœÐ°Ñ ÑÑÑПка" |
-
diff --git tests/data/construct-python-long-short.code tests/data/construct-python-long-short.code
index fafc3f1..190a180 100644
-
diff --git tests/data/construct-python-name-module.code tests/data/construct-python-name-module.code
index 335c7ca..4e6a519 100644
|
|
|
|
| 1 | | [file, Loader, dump, abs, yaml.tokens] |
| | 1 | [list, Loader, dump, abs, yaml.tokens] |
-
diff --git tests/data/construct-python-name-module.data tests/data/construct-python-name-module.data
index c8f8036..7f1cc20 100644
|
|
|
|
| 1 | | - !!python/name:file |
| | 1 | - !!python/name:list |
| 2 | 2 | - !!python/name:yaml.Loader |
| 3 | 3 | - !!python/name:yaml.dump |
| 4 | 4 | - !!python/name:abs |
-
diff --git tests/data/construct-python-object.code tests/data/construct-python-object.code
index 7f1edf1..651a669 100644
|
|
|
|
| 1 | 1 | [ |
| 2 | 2 | AnObject(1, 'two', [3,3,3]), |
| 3 | | AnInstance(1, 'two', [3,3,3]), |
| 4 | 3 | |
| 5 | 4 | AnObject(1, 'two', [3,3,3]), |
| 6 | | AnInstance(1, 'two', [3,3,3]), |
| 7 | 5 | |
| 8 | 6 | AState(1, 'two', [3,3,3]), |
| 9 | 7 | ACustomState(1, 'two', [3,3,3]), |
| 10 | 8 | |
| 11 | | InitArgs(1, 'two', [3,3,3]), |
| 12 | | InitArgsWithState(1, 'two', [3,3,3]), |
| 13 | | |
| 14 | 9 | NewArgs(1, 'two', [3,3,3]), |
| 15 | 10 | NewArgsWithState(1, 'two', [3,3,3]), |
| 16 | 11 | |
-
diff --git tests/data/construct-python-object.data tests/data/construct-python-object.data
index bce8b2e..2414f09 100644
|
|
|
|
| 1 | 1 | - !!python/object:test_constructor.AnObject { foo: 1, bar: two, baz: [3,3,3] } |
| 2 | | - !!python/object:test_constructor.AnInstance { foo: 1, bar: two, baz: [3,3,3] } |
| 3 | 2 | |
| 4 | 3 | - !!python/object/new:test_constructor.AnObject { args: [1, two], kwds: {baz: [3,3,3]} } |
| 5 | | - !!python/object/apply:test_constructor.AnInstance { args: [1, two], kwds: {baz: [3,3,3]} } |
| 6 | 4 | |
| 7 | 5 | - !!python/object:test_constructor.AState { _foo: 1, _bar: two, _baz: [3,3,3] } |
| 8 | 6 | - !!python/object/new:test_constructor.ACustomState { state: !!python/tuple [1, two, [3,3,3]] } |
| 9 | 7 | |
| 10 | | - !!python/object/new:test_constructor.InitArgs [1, two, [3,3,3]] |
| 11 | | - !!python/object/new:test_constructor.InitArgsWithState { args: [1, two], state: [3,3,3] } |
| 12 | | |
| 13 | 8 | - !!python/object/new:test_constructor.NewArgs [1, two, [3,3,3]] |
| 14 | 9 | - !!python/object/new:test_constructor.NewArgsWithState { args: [1, two], state: [3,3,3] } |
| 15 | 10 | |
-
diff --git tests/data/construct-python-str-utf8.code tests/data/construct-python-str-utf8.code
index 47b28ab..9f66032 100644
|
|
|
|
| 1 | | u'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430'.encode('utf-8') |
| | 1 | '\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' |
-
diff --git tests/data/construct-python-unicode-ascii.code tests/data/construct-python-unicode-ascii.code
deleted file mode 100644
index d4cd82c..0000000
-
diff --git tests/data/construct-python-unicode-ascii.data tests/data/construct-python-unicode-ascii.data
deleted file mode 100644
index 3a0647b..0000000
|
+
|
-
|
|
| 1 | | --- !!python/unicode "ascii string" |
-
diff --git tests/data/construct-python-unicode-utf8.code tests/data/construct-python-unicode-utf8.code
deleted file mode 100644
index 2793ac7..0000000
|
+
|
-
|
|
| 1 | | u'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' |
-
diff --git tests/data/construct-python-unicode-utf8.data tests/data/construct-python-unicode-utf8.data
deleted file mode 100644
index 5a980ea..0000000
|
+
|
-
|
|
| 1 | | --- !!python/unicode "ÐÑП ÑÐœÐžÐºÐŸÐŽÐœÐ°Ñ ÑÑÑПка" |
-
diff --git tests/data/construct-str-utf8.code tests/data/construct-str-utf8.code
index 2793ac7..9f66032 100644
|
|
|
|
| 1 | | u'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' |
| | 1 | '\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' |
-
diff --git tests/data/emitting-unacceptable-unicode-character-bug.code tests/data/emitting-unacceptable-unicode-character-bug.code
index 4b92854..2a5df00 100644
-
diff --git tests/data/recursive-set.recursive tests/data/recursive-set.recursive
index 457c50d..d1a7ca3 100644
|
|
|
|
| 1 | | try: |
| 2 | | set |
| 3 | | except NameError: |
| 4 | | from sets import Set as set |
| 5 | 1 | value = set() |
| 6 | 2 | value.add(AnInstance(foo=value, bar=value)) |
| 7 | 3 | value.add(AnInstance(foo=value, bar=value)) |
-
diff --git tests/data/serializer-is-already-opened.dumper-error tests/data/serializer-is-already-opened.dumper-error
index 0f66a46..c2be9bb 100644
|
|
|
|
| 1 | | dumper = Dumper(StringIO.StringIO()) |
| | 1 | dumper = Dumper(io.StringIO()) |
| 2 | 2 | dumper.open() |
| 3 | 3 | dumper.open() |
-
diff --git tests/data/serializer-is-closed-1.dumper-error tests/data/serializer-is-closed-1.dumper-error
index 5d9ecfc..93dcd66 100644
|
|
|
|
| 1 | | dumper = Dumper(StringIO.StringIO()) |
| | 1 | dumper = Dumper(io.StringIO()) |
| 2 | 2 | dumper.open() |
| 3 | 3 | dumper.close() |
| 4 | 4 | dumper.open() |
-
diff --git tests/data/serializer-is-closed-2.dumper-error tests/data/serializer-is-closed-2.dumper-error
index 0762145..e15fb9d 100644
|
|
|
|
| 1 | | dumper = Dumper(StringIO.StringIO()) |
| | 1 | dumper = Dumper(io.StringIO()) |
| 2 | 2 | dumper.open() |
| 3 | 3 | dumper.close() |
| 4 | 4 | dumper.serialize(ScalarNode(tag='!foo', value='bar')) |
-
diff --git tests/data/serializer-is-not-opened-1.dumper-error tests/data/serializer-is-not-opened-1.dumper-error
index 1d21554..8f68baf 100644
|
|
|
|
| 1 | | dumper = Dumper(StringIO.StringIO()) |
| | 1 | dumper = Dumper(io.StringIO()) |
| 2 | 2 | dumper.close() |
-
diff --git tests/data/serializer-is-not-opened-2.dumper-error tests/data/serializer-is-not-opened-2.dumper-error
index d1d7f98..e818837 100644
|
|
|
|
| 1 | | dumper = Dumper(StringIO.StringIO()) |
| | 1 | dumper = Dumper(io.StringIO()) |
| 2 | 2 | dumper.serialize(ScalarNode(tag='!foo', value='bar')) |
-
diff --git tests/test_appliance.py tests/test_appliance.py
index d5e5d3e..5f3c23f 100644
|
|
|
class Error(Exception): |
| 43 | 43 | class CanonicalScanner: |
| 44 | 44 | |
| 45 | 45 | def __init__(self, data): |
| 46 | | self.data = unicode(data, 'utf-8')+u'\0' |
| | 46 | self.data = str(data, 'utf-8')+'\0' |
| 47 | 47 | self.index = 0 |
| 48 | 48 | self.scan() |
| 49 | 49 | |
| … |
… |
class CanonicalScanner: |
| 76 | 76 | while True: |
| 77 | 77 | self.find_token() |
| 78 | 78 | ch = self.data[self.index] |
| 79 | | if ch == u'\0': |
| | 79 | if ch == '\0': |
| 80 | 80 | self.tokens.append(StreamEndToken(None, None)) |
| 81 | 81 | break |
| 82 | | elif ch == u'%': |
| | 82 | elif ch == '%': |
| 83 | 83 | self.tokens.append(self.scan_directive()) |
| 84 | | elif ch == u'-' and self.data[self.index:self.index+3] == u'---': |
| | 84 | elif ch == '-' and self.data[self.index:self.index+3] == '---': |
| 85 | 85 | self.index += 3 |
| 86 | 86 | self.tokens.append(DocumentStartToken(None, None)) |
| 87 | | elif ch == u'[': |
| | 87 | elif ch == '[': |
| 88 | 88 | self.index += 1 |
| 89 | 89 | self.tokens.append(FlowSequenceStartToken(None, None)) |
| 90 | | elif ch == u'{': |
| | 90 | elif ch == '{': |
| 91 | 91 | self.index += 1 |
| 92 | 92 | self.tokens.append(FlowMappingStartToken(None, None)) |
| 93 | | elif ch == u']': |
| | 93 | elif ch == ']': |
| 94 | 94 | self.index += 1 |
| 95 | 95 | self.tokens.append(FlowSequenceEndToken(None, None)) |
| 96 | | elif ch == u'}': |
| | 96 | elif ch == '}': |
| 97 | 97 | self.index += 1 |
| 98 | 98 | self.tokens.append(FlowMappingEndToken(None, None)) |
| 99 | | elif ch == u'?': |
| | 99 | elif ch == '?': |
| 100 | 100 | self.index += 1 |
| 101 | 101 | self.tokens.append(KeyToken(None, None)) |
| 102 | | elif ch == u':': |
| | 102 | elif ch == ':': |
| 103 | 103 | self.index += 1 |
| 104 | 104 | self.tokens.append(ValueToken(None, None)) |
| 105 | | elif ch == u',': |
| | 105 | elif ch == ',': |
| 106 | 106 | self.index += 1 |
| 107 | 107 | self.tokens.append(FlowEntryToken(None, None)) |
| 108 | | elif ch == u'*' or ch == u'&': |
| | 108 | elif ch == '*' or ch == '&': |
| 109 | 109 | self.tokens.append(self.scan_alias()) |
| 110 | | elif ch == u'!': |
| | 110 | elif ch == '!': |
| 111 | 111 | self.tokens.append(self.scan_tag()) |
| 112 | | elif ch == u'"': |
| | 112 | elif ch == '"': |
| 113 | 113 | self.tokens.append(self.scan_scalar()) |
| 114 | 114 | else: |
| 115 | 115 | raise Error("invalid token") |
| 116 | 116 | |
| 117 | | DIRECTIVE = u'%YAML 1.1' |
| | 117 | DIRECTIVE = '%YAML 1.1' |
| 118 | 118 | |
| 119 | 119 | def scan_directive(self): |
| 120 | 120 | if self.data[self.index:self.index+len(self.DIRECTIVE)] == self.DIRECTIVE and \ |
| 121 | | self.data[self.index+len(self.DIRECTIVE)] in u' \n\0': |
| | 121 | self.data[self.index+len(self.DIRECTIVE)] in ' \n\0': |
| 122 | 122 | self.index += len(self.DIRECTIVE) |
| 123 | 123 | return DirectiveToken('YAML', (1, 1), None, None) |
| 124 | 124 | |
| 125 | 125 | def scan_alias(self): |
| 126 | | if self.data[self.index] == u'*': |
| | 126 | if self.data[self.index] == '*': |
| 127 | 127 | TokenClass = AliasToken |
| 128 | 128 | else: |
| 129 | 129 | TokenClass = AnchorToken |
| 130 | 130 | self.index += 1 |
| 131 | 131 | start = self.index |
| 132 | | while self.data[self.index] not in u', \n\0': |
| | 132 | while self.data[self.index] not in ', \n\0': |
| 133 | 133 | self.index += 1 |
| 134 | 134 | value = self.data[start:self.index] |
| 135 | 135 | return TokenClass(value, None, None) |
| … |
… |
class CanonicalScanner: |
| 137 | 137 | def scan_tag(self): |
| 138 | 138 | self.index += 1 |
| 139 | 139 | start = self.index |
| 140 | | while self.data[self.index] not in u' \n\0': |
| | 140 | while self.data[self.index] not in ' \n\0': |
| 141 | 141 | self.index += 1 |
| 142 | 142 | value = self.data[start:self.index] |
| 143 | | if value[0] == u'!': |
| | 143 | if value[0] == '!': |
| 144 | 144 | value = 'tag:yaml.org,2002:'+value[1:] |
| 145 | | elif value[0] == u'<' and value[-1] == u'>': |
| | 145 | elif value[0] == '<' and value[-1] == '>': |
| 146 | 146 | value = value[1:-1] |
| 147 | 147 | else: |
| 148 | | value = u'!'+value |
| | 148 | value = '!'+value |
| 149 | 149 | return TagToken(value, None, None) |
| 150 | 150 | |
| 151 | 151 | QUOTE_CODES = { |
| … |
… |
class CanonicalScanner: |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | QUOTE_REPLACES = { |
| 158 | | u'\\': u'\\', |
| 159 | | u'\"': u'\"', |
| 160 | | u' ': u' ', |
| 161 | | u'a': u'\x07', |
| 162 | | u'b': u'\x08', |
| 163 | | u'e': u'\x1B', |
| 164 | | u'f': u'\x0C', |
| 165 | | u'n': u'\x0A', |
| 166 | | u'r': u'\x0D', |
| 167 | | u't': u'\x09', |
| 168 | | u'v': u'\x0B', |
| 169 | | u'N': u'\u0085', |
| 170 | | u'L': u'\u2028', |
| 171 | | u'P': u'\u2029', |
| 172 | | u'_': u'_', |
| 173 | | u'0': u'\x00', |
| | 158 | '\\': '\\', |
| | 159 | '\"': '\"', |
| | 160 | ' ': ' ', |
| | 161 | 'a': '\x07', |
| | 162 | 'b': '\x08', |
| | 163 | 'e': '\x1B', |
| | 164 | 'f': '\x0C', |
| | 165 | 'n': '\x0A', |
| | 166 | 'r': '\x0D', |
| | 167 | 't': '\x09', |
| | 168 | 'v': '\x0B', |
| | 169 | 'N': '\u0085', |
| | 170 | 'L': '\u2028', |
| | 171 | 'P': '\u2029', |
| | 172 | '_': '_', |
| | 173 | '0': '\x00', |
| 174 | 174 | |
| 175 | 175 | } |
| 176 | 176 | |
| … |
… |
class CanonicalScanner: |
| 179 | 179 | chunks = [] |
| 180 | 180 | start = self.index |
| 181 | 181 | ignore_spaces = False |
| 182 | | while self.data[self.index] != u'"': |
| 183 | | if self.data[self.index] == u'\\': |
| | 182 | while self.data[self.index] != '"': |
| | 183 | if self.data[self.index] == '\\': |
| 184 | 184 | ignore_spaces = False |
| 185 | 185 | chunks.append(self.data[start:self.index]) |
| 186 | 186 | self.index += 1 |
| 187 | 187 | ch = self.data[self.index] |
| 188 | 188 | self.index += 1 |
| 189 | | if ch == u'\n': |
| | 189 | if ch == '\n': |
| 190 | 190 | ignore_spaces = True |
| 191 | 191 | elif ch in self.QUOTE_CODES: |
| 192 | 192 | length = self.QUOTE_CODES[ch] |
| 193 | 193 | code = int(self.data[self.index:self.index+length], 16) |
| 194 | | chunks.append(unichr(code)) |
| | 194 | chunks.append(chr(code)) |
| 195 | 195 | self.index += length |
| 196 | 196 | else: |
| 197 | 197 | chunks.append(self.QUOTE_REPLACES[ch]) |
| 198 | 198 | start = self.index |
| 199 | | elif self.data[self.index] == u'\n': |
| | 199 | elif self.data[self.index] == '\n': |
| 200 | 200 | chunks.append(self.data[start:self.index]) |
| 201 | | chunks.append(u' ') |
| | 201 | chunks.append(' ') |
| 202 | 202 | self.index += 1 |
| 203 | 203 | start = self.index |
| 204 | 204 | ignore_spaces = True |
| 205 | | elif ignore_spaces and self.data[self.index] == u' ': |
| | 205 | elif ignore_spaces and self.data[self.index] == ' ': |
| 206 | 206 | self.index += 1 |
| 207 | 207 | start = self.index |
| 208 | 208 | else: |
| … |
… |
class CanonicalScanner: |
| 210 | 210 | self.index += 1 |
| 211 | 211 | chunks.append(self.data[start:self.index]) |
| 212 | 212 | self.index += 1 |
| 213 | | return ScalarToken(u''.join(chunks), False, None, None) |
| | 213 | return ScalarToken(''.join(chunks), False, None, None) |
| 214 | 214 | |
| 215 | 215 | def find_token(self): |
| 216 | 216 | found = False |
| 217 | 217 | while not found: |
| 218 | | while self.data[self.index] in u' \t': |
| | 218 | while self.data[self.index] in ' \t': |
| 219 | 219 | self.index += 1 |
| 220 | | if self.data[self.index] == u'#': |
| 221 | | while self.data[self.index] != u'\n': |
| | 220 | if self.data[self.index] == '#': |
| | 221 | while self.data[self.index] != '\n': |
| 222 | 222 | self.index += 1 |
| 223 | | if self.data[self.index] == u'\n': |
| | 223 | if self.data[self.index] == '\n': |
| 224 | 224 | self.index += 1 |
| 225 | 225 | else: |
| 226 | 226 | found = True |
-
diff --git tests/test_canonical.py tests/test_canonical.py
index 4416902..73804bc 100644
|
|
|
import test_appliance |
| 4 | 4 | class TestCanonicalAppliance(test_appliance.TestAppliance): |
| 5 | 5 | |
| 6 | 6 | def _testCanonicalScanner(self, test_name, canonical_filename): |
| 7 | | data = file(canonical_filename, 'rb').read() |
| | 7 | data = open(canonical_filename, 'rb').read() |
| 8 | 8 | tokens = list(test_appliance.canonical_scan(data)) |
| 9 | 9 | #for token in tokens: |
| 10 | | # print token |
| | 10 | # print(token) |
| 11 | 11 | |
| 12 | 12 | def _testCanonicalParser(self, test_name, canonical_filename): |
| 13 | | data = file(canonical_filename, 'rb').read() |
| | 13 | data = open(canonical_filename, 'rb').read() |
| 14 | 14 | event = list(test_appliance.canonical_parse(data)) |
| 15 | 15 | #for event in events: |
| 16 | | # print event |
| | 16 | # print(event) |
| 17 | 17 | |
| 18 | 18 | TestCanonicalAppliance.add_tests('testCanonicalScanner', '.canonical') |
| 19 | 19 | TestCanonicalAppliance.add_tests('testCanonicalParser', '.canonical') |
-
diff --git tests/test_constructor.py tests/test_constructor.py
index 04f54ef..3d72e5f 100644
|
|
|
|
| 2 | 2 | import test_appliance |
| 3 | 3 | |
| 4 | 4 | import datetime |
| 5 | | try: |
| 6 | | set |
| 7 | | except NameError: |
| 8 | | from sets import Set as set |
| 9 | 5 | |
| 10 | 6 | from yaml import * |
| 11 | 7 | |
| … |
… |
class YAMLObject2(YAMLObject): |
| 111 | 107 | else: |
| 112 | 108 | return False |
| 113 | 109 | |
| 114 | | class AnObject(object): |
| | 110 | class AnObject: |
| 115 | 111 | |
| 116 | 112 | def __new__(cls, foo=None, bar=None, baz=None): |
| 117 | 113 | self = object.__new__(cls) |
| … |
… |
class AnObject(object): |
| 128 | 124 | return type(self) is type(other) and \ |
| 129 | 125 | (self.foo, self.bar, self.baz) == (other.foo, other.bar, other.baz) |
| 130 | 126 | |
| 131 | | class AnInstance: |
| | 127 | def __repr__(self): |
| | 128 | return '%s(foo=%r, bar=%r, baz=%r)' % \ |
| | 129 | (self.__class__.__name__, self.foo, self.bar, self.baz) |
| 132 | 130 | |
| 133 | | def __init__(self, foo=None, bar=None, baz=None): |
| 134 | | self.foo = foo |
| 135 | | self.bar = bar |
| 136 | | self.baz = baz |
| 137 | | |
| 138 | | def __cmp__(self, other): |
| 139 | | return cmp((type(self), self.foo, self.bar, self.baz), |
| 140 | | (type(other), other.foo, other.bar, other.baz)) |
| 141 | | |
| 142 | | def __eq__(self, other): |
| 143 | | return type(self) is type(other) and \ |
| 144 | | (self.foo, self.bar, self.baz) == (other.foo, other.bar, other.baz) |
| 145 | | |
| 146 | | class AState(AnInstance): |
| | 131 | class AState(AnObject): |
| 147 | 132 | |
| 148 | 133 | def __getstate__(self): |
| 149 | 134 | return { |
| … |
… |
class AState(AnInstance): |
| 157 | 142 | self.bar = state['_bar'] |
| 158 | 143 | self.baz = state['_baz'] |
| 159 | 144 | |
| 160 | | class ACustomState(AnInstance): |
| | 145 | class ACustomState(AnObject): |
| 161 | 146 | |
| 162 | 147 | def __getstate__(self): |
| 163 | 148 | return (self.foo, self.bar, self.baz) |
| … |
… |
class ACustomState(AnInstance): |
| 165 | 150 | def __setstate__(self, state): |
| 166 | 151 | self.foo, self.bar, self.baz = state |
| 167 | 152 | |
| 168 | | class InitArgs(AnInstance): |
| 169 | | |
| 170 | | def __getinitargs__(self): |
| 171 | | return (self.foo, self.bar, self.baz) |
| 172 | | |
| 173 | | def __getstate__(self): |
| 174 | | return {} |
| 175 | | |
| 176 | | class InitArgsWithState(AnInstance): |
| 177 | | |
| 178 | | def __getinitargs__(self): |
| 179 | | return (self.foo, self.bar) |
| 180 | | |
| 181 | | def __getstate__(self): |
| 182 | | return self.baz |
| 183 | | |
| 184 | | def __setstate__(self, state): |
| 185 | | self.baz = state |
| 186 | | |
| 187 | 153 | class NewArgs(AnObject): |
| 188 | 154 | |
| 189 | 155 | def __getnewargs__(self): |
| … |
… |
class FixedOffset(datetime.tzinfo): |
| 255 | 221 | |
| 256 | 222 | |
| 257 | 223 | def execute(code): |
| 258 | | exec code |
| | 224 | exec(code) |
| 259 | 225 | return value |
| 260 | 226 | |
| 261 | 227 | class TestConstructorTypes(test_appliance.TestAppliance): |
| … |
… |
class TestConstructorTypes(test_appliance.TestAppliance): |
| 264 | 230 | data1 = None |
| 265 | 231 | data2 = None |
| 266 | 232 | try: |
| 267 | | data1 = list(load_all(file(data_filename, 'rb'), Loader=MyLoader)) |
| | 233 | data1 = list(load_all(open(data_filename, 'rb'), Loader=MyLoader)) |
| 268 | 234 | if len(data1) == 1: |
| 269 | 235 | data1 = data1[0] |
| 270 | | data2 = eval(file(code_filename, 'rb').read()) |
| | 236 | data2 = eval(open(code_filename, 'rb').read()) |
| 271 | 237 | self.failUnlessEqual(type(data1), type(data2)) |
| 272 | 238 | try: |
| 273 | 239 | self.failUnlessEqual(data1, data2) |
| … |
… |
class TestConstructorTypes(test_appliance.TestAppliance): |
| 300 | 266 | else: |
| 301 | 267 | raise |
| 302 | 268 | except: |
| 303 | | print |
| 304 | | print "DATA:" |
| 305 | | print file(data_filename, 'rb').read() |
| 306 | | print "CODE:" |
| 307 | | print file(code_filename, 'rb').read() |
| 308 | | print "NATIVES1:", data1 |
| 309 | | print "NATIVES2:", data2 |
| | 269 | print() |
| | 270 | print("DATA:") |
| | 271 | print(open(data_filename, 'rb').read()) |
| | 272 | print("CODE:") |
| | 273 | print(open(code_filename, 'rb').read()) |
| | 274 | print("NATIVES1:", repr(data1)) |
| | 275 | print("NATIVES2:", repr(data2)) |
| 310 | 276 | raise |
| 311 | 277 | |
| 312 | 278 | TestConstructorTypes.add_tests('testTypes', '.data', '.code') |
-
diff --git tests/test_emitter.py tests/test_emitter.py
index d45cd8f..bf93dba 100644
|
|
|
|
| 1 | 1 | |
| 2 | | import test_appliance, sys, StringIO |
| | 2 | import test_appliance, sys, io |
| 3 | 3 | |
| 4 | 4 | from yaml import * |
| 5 | 5 | import yaml |
| … |
… |
class TestEmitter(test_appliance.TestAppliance): |
| 16 | 16 | self._testEmitter(test_name, canonical_filename, True) |
| 17 | 17 | |
| 18 | 18 | def _testEmitter(self, test_name, filename, canonical=None): |
| 19 | | events = list(parse(file(filename, 'rb'))) |
| | 19 | events = list(parse(open(filename, 'rb'))) |
| 20 | 20 | #self._dump(filename, events, canonical) |
| 21 | | stream = StringIO.StringIO() |
| | 21 | stream = io.StringIO() |
| 22 | 22 | emit(events, stream, canonical=canonical) |
| 23 | 23 | data = stream.getvalue() |
| 24 | 24 | new_events = list(parse(data)) |
| … |
… |
class TestEmitter(test_appliance.TestAppliance): |
| 35 | 35 | self.failUnlessEqual(event.value, new_event.value) |
| 36 | 36 | |
| 37 | 37 | def _dump(self, filename, events, canonical): |
| 38 | | print "="*30 |
| 39 | | print "ORIGINAL DOCUMENT:" |
| 40 | | print file(filename, 'rb').read() |
| 41 | | print '-'*30 |
| 42 | | print "EMITTED DOCUMENT:" |
| | 38 | print("="*30) |
| | 39 | print("ORIGINAL DOCUMENT:") |
| | 40 | print(open(filename, 'rb').read()) |
| | 41 | print('-'*30) |
| | 42 | print("EMITTED DOCUMENT:") |
| 43 | 43 | emit(events, sys.stdout, canonical=canonical) |
| 44 | 44 | |
| 45 | 45 | TestEmitter.add_tests('testEmitterOnData', '.canonical', '.data') |
| … |
… |
EventsLoader.add_constructor(None, EventsLoader.construct_event) |
| 71 | 71 | class TestEmitterEvents(test_appliance.TestAppliance): |
| 72 | 72 | |
| 73 | 73 | def _testEmitterEvents(self, test_name, events_filename): |
| 74 | | events = list(load(file(events_filename, 'rb'), Loader=EventsLoader)) |
| | 74 | events = list(load(open(events_filename, 'rb'), Loader=EventsLoader)) |
| 75 | 75 | #self._dump(events_filename, events) |
| 76 | | stream = StringIO.StringIO() |
| | 76 | stream = io.StringIO() |
| 77 | 77 | emit(events, stream) |
| 78 | 78 | data = stream.getvalue() |
| 79 | 79 | new_events = list(parse(data)) |
| … |
… |
class TestEmitterEvents(test_appliance.TestAppliance): |
| 90 | 90 | self.failUnlessEqual(event.value, new_event.value) |
| 91 | 91 | |
| 92 | 92 | def _dump(self, events_filename, events): |
| 93 | | print "="*30 |
| 94 | | print "EVENTS:" |
| 95 | | print file(events_filename, 'rb').read() |
| 96 | | print '-'*30 |
| 97 | | print "OUTPUT:" |
| | 93 | print("="*30) |
| | 94 | print("EVENTS:") |
| | 95 | print(open(events_filename, 'rb').read()) |
| | 96 | print('-'*30) |
| | 97 | print("OUTPUT:") |
| 98 | 98 | emit(events, sys.stdout) |
| 99 | 99 | |
| 100 | 100 | TestEmitterEvents.add_tests('testEmitterEvents', '.events') |
-
diff --git tests/test_errors.py tests/test_errors.py
index 7d6e0d2..02df778 100644
|
|
|
|
| 2 | 2 | import test_appliance |
| 3 | 3 | import test_emitter |
| 4 | 4 | |
| 5 | | import StringIO |
| | 5 | import io |
| 6 | 6 | |
| 7 | 7 | from yaml import * |
| 8 | 8 | |
| … |
… |
class TestErrors(test_appliance.TestAppliance): |
| 21 | 21 | self.failUnlessRaises(YAMLError, lambda: self._load_single(invalid_filename)) |
| 22 | 22 | |
| 23 | 23 | def _testEmitterErrors(self, test_name, invalid_filename): |
| 24 | | events = list(load(file(invalid_filename, 'rb').read(), |
| | 24 | events = list(load(open(invalid_filename, 'rb').read(), |
| 25 | 25 | Loader=test_emitter.EventsLoader)) |
| 26 | 26 | self.failUnlessRaises(YAMLError, lambda: self._emit(events)) |
| 27 | 27 | |
| 28 | 28 | def _testDumperErrors(self, test_name, invalid_filename): |
| 29 | | code = file(invalid_filename, 'rb').read() |
| | 29 | code = open(invalid_filename, 'r').read() |
| 30 | 30 | self.failUnlessRaises(YAMLError, lambda: self._dump(code)) |
| 31 | 31 | |
| 32 | 32 | def _dump(self, code): |
| 33 | 33 | try: |
| 34 | | exec code |
| 35 | | except YAMLError, exc: |
| 36 | | #print '.'*70 |
| 37 | | #print "%s:" % exc.__class__.__name__, exc |
| | 34 | exec(code) |
| | 35 | except YAMLError as exc: |
| | 36 | #print('.'*70) |
| | 37 | #print("%s:" % exc.__class__.__name__, exc) |
| 38 | 38 | raise |
| 39 | 39 | |
| 40 | 40 | def _emit(self, events): |
| 41 | 41 | try: |
| 42 | 42 | emit(events) |
| 43 | | except YAMLError, exc: |
| 44 | | #print '.'*70 |
| 45 | | #print "%s:" % exc.__class__.__name__, exc |
| | 43 | except YAMLError as exc: |
| | 44 | #print('.'*70) |
| | 45 | #print("%s:" % exc.__class__.__name__, exc) |
| 46 | 46 | raise |
| 47 | 47 | |
| 48 | 48 | def _load(self, filename): |
| 49 | 49 | try: |
| 50 | | return list(load_all(file(filename, 'rb'))) |
| 51 | | except YAMLError, exc: |
| | 50 | return list(load_all(open(filename, 'rb'))) |
| | 51 | except YAMLError as exc: |
| 52 | 52 | #except ScannerError, exc: |
| 53 | 53 | #except ParserError, exc: |
| 54 | 54 | #except ComposerError, exc: |
| 55 | 55 | #except ConstructorError, exc: |
| 56 | | #print '.'*70 |
| 57 | | #print "%s:" % exc.__class__.__name__, exc |
| | 56 | #print('.'*70) |
| | 57 | #print("%s:" % exc.__class__.__name__, exc) |
| 58 | 58 | raise |
| 59 | 59 | |
| 60 | 60 | def _load_string(self, filename): |
| 61 | 61 | try: |
| 62 | | return list(load_all(file(filename, 'rb').read())) |
| 63 | | except YAMLError, exc: |
| | 62 | return list(load_all(open(filename, 'rb').read())) |
| | 63 | except YAMLError as exc: |
| 64 | 64 | #except ScannerError, exc: |
| 65 | 65 | #except ParserError, exc: |
| 66 | 66 | #except ComposerError, exc: |
| 67 | 67 | #except ConstructorError, exc: |
| 68 | | #print '.'*70 |
| 69 | | #print "%s:" % filename |
| 70 | | #print "%s:" % exc.__class__.__name__, exc |
| | 68 | #print('.'*70) |
| | 69 | #print("%s:" % filename) |
| | 70 | #print("%s:" % exc.__class__.__name__, exc) |
| 71 | 71 | raise |
| 72 | 72 | |
| 73 | 73 | def _load_single(self, filename): |
| 74 | 74 | try: |
| 75 | | return load(file(filename, 'rb').read()) |
| 76 | | except YAMLError, exc: |
| | 75 | return load(open(filename, 'rb').read()) |
| | 76 | except YAMLError as exc: |
| 77 | 77 | #except ScannerError, exc: |
| 78 | 78 | #except ParserError, exc: |
| 79 | 79 | #except ComposerError, exc: |
| 80 | 80 | #except ConstructorError, exc: |
| 81 | | #print '.'*70 |
| 82 | | #print "%s:" % filename |
| 83 | | #print "%s:" % exc.__class__.__name__, exc |
| | 81 | #print('.'*70) |
| | 82 | #print("%s:" % filename) |
| | 83 | #print("%s:" % exc.__class__.__name__, exc) |
| 84 | 84 | raise |
| 85 | 85 | |
| 86 | 86 | TestErrors.add_tests('testLoaderErrors', '.loader-error') |
-
diff --git tests/test_mark.py tests/test_mark.py
index 4fa665e..12f73fa 100644
|
|
|
from yaml.reader import Mark |
| 6 | 6 | class TestMark(test_appliance.TestAppliance): |
| 7 | 7 | |
| 8 | 8 | def _testMarks(self, test_name, marks_filename): |
| 9 | | inputs = file(marks_filename, 'rb').read().split('---\n')[1:] |
| | 9 | inputs = open(marks_filename, 'r').read().split('---\n')[1:] |
| 10 | 10 | for input in inputs: |
| 11 | 11 | index = 0 |
| 12 | 12 | line = 0 |
| … |
… |
class TestMark(test_appliance.TestAppliance): |
| 18 | 18 | else: |
| 19 | 19 | column += 1 |
| 20 | 20 | index += 1 |
| 21 | | mark = Mark(test_name, index, line, column, unicode(input), index) |
| | 21 | mark = Mark(test_name, index, line, column, input, index) |
| 22 | 22 | snippet = mark.get_snippet(indent=2, max_length=79) |
| 23 | | #print "INPUT:" |
| 24 | | #print input |
| 25 | | #print "SNIPPET:" |
| 26 | | #print snippet |
| | 23 | #print("INPUT:") |
| | 24 | #print(input) |
| | 25 | #print("SNIPPET:") |
| | 26 | #print(snippet) |
| 27 | 27 | self.failUnless(isinstance(snippet, str)) |
| 28 | 28 | self.failUnlessEqual(snippet.count('\n'), 1) |
| 29 | 29 | data, pointer = snippet.split('\n') |
-
diff --git tests/test_reader.py tests/test_reader.py
index 1bfae1a..bafae4e 100644
|
|
|
class TestReaderErrors(test_appliance.TestAppliance): |
| 9 | 9 | def _testReaderUnicodeErrors(self, test_name, stream_filename): |
| 10 | 10 | for encoding in ['utf-8', 'utf-16-le', 'utf-16-be']: |
| 11 | 11 | try: |
| 12 | | data = unicode(file(stream_filename, 'rb').read(), encoding) |
| | 12 | data = open(stream_filename, 'rb').read().decode(encoding) |
| 13 | 13 | break |
| 14 | 14 | except: |
| 15 | 15 | pass |
| … |
… |
class TestReaderErrors(test_appliance.TestAppliance): |
| 22 | 22 | self.failUnlessRaises(ReaderError, |
| 23 | 23 | lambda: self._load(codecs.open(stream_filename, encoding=encoding))) |
| 24 | 24 | |
| 25 | | def _testReaderStringErrors(self, test_name, stream_filename): |
| 26 | | data = file(stream_filename, 'rb').read() |
| | 25 | def _testReaderBytesErrors(self, test_name, stream_filename): |
| | 26 | data = open(stream_filename, 'rb').read() |
| 27 | 27 | #self._load(data) |
| 28 | 28 | self.failUnlessRaises(ReaderError, lambda: self._load(data)) |
| 29 | 29 | |
| 30 | 30 | def _testReaderFileErrors(self, test_name, stream_filename): |
| 31 | | data = file(stream_filename, 'rb') |
| | 31 | data = open(stream_filename, 'rb').read() |
| 32 | 32 | #self._load(data) |
| 33 | 33 | self.failUnlessRaises(ReaderError, lambda: self._load(data)) |
| 34 | 34 | |
| 35 | 35 | def _load(self, data): |
| 36 | 36 | stream = Reader(data) |
| 37 | | while stream.peek() != u'\0': |
| | 37 | while stream.peek() != '\0': |
| 38 | 38 | stream.forward() |
| 39 | 39 | |
| 40 | 40 | TestReaderErrors.add_tests('testReaderUnicodeErrors', '.stream-error') |
| 41 | | TestReaderErrors.add_tests('testReaderStringErrors', '.stream-error') |
| | 41 | TestReaderErrors.add_tests('testReaderBytesErrors', '.stream-error') |
| 42 | 42 | TestReaderErrors.add_tests('testReaderFileErrors', '.stream-error') |
| 43 | 43 | |
| 44 | 44 | |
-
diff --git tests/test_recursive.py tests/test_recursive.py
index 3c09264..a9cac1f 100644
|
|
|
class AnInstanceWithState(AnInstance): |
| 27 | 27 | class TestRecursive(test_appliance.TestAppliance): |
| 28 | 28 | |
| 29 | 29 | def _testRecursive(self, test_name, recursive_filename): |
| 30 | | exec file(recursive_filename, 'r').read() |
| 31 | | value1 = value |
| | 30 | exec(open(recursive_filename, 'r').read()) |
| | 31 | value1 = locals()['value'] |
| 32 | 32 | output1 = None |
| 33 | 33 | value2 = None |
| 34 | 34 | output2 = None |
| 35 | 35 | try: |
| 36 | 36 | output1 = dump(value1) |
| 37 | | #print "OUTPUT %s:" % test_name |
| 38 | | #print output1 |
| | 37 | #print("OUTPUT %s:" % test_name) |
| | 38 | #print(output1) |
| 39 | 39 | value2 = load(output1) |
| 40 | 40 | output2 = dump(value2) |
| 41 | 41 | self.failUnlessEqual(output1, output2) |
| 42 | 42 | except: |
| 43 | | print "VALUE1:", value1 |
| 44 | | print "VALUE2:", value2 |
| 45 | | print "OUTPUT1:" |
| 46 | | print output1 |
| 47 | | print "OUTPUT2:" |
| 48 | | print output2 |
| | 43 | print("VALUE1:", value1) |
| | 44 | print("VALUE2:", value2) |
| | 45 | print("OUTPUT1:") |
| | 46 | print(output1) |
| | 47 | print("OUTPUT2:") |
| | 48 | print(output2) |
| 49 | 49 | raise |
| 50 | 50 | |
| 51 | 51 | TestRecursive.add_tests('testRecursive', '.recursive') |
-
diff --git tests/test_representer.py tests/test_representer.py
index 6746146..665def6 100644
|
|
|
class TestRepresenterTypes(test_appliance.TestAppliance): |
| 10 | 10 | return self._testTypes(test_name, data_filename, code_filename, allow_unicode=True) |
| 11 | 11 | |
| 12 | 12 | def _testTypes(self, test_name, data_filename, code_filename, allow_unicode=False): |
| 13 | | data1 = eval(file(code_filename, 'rb').read()) |
| | 13 | data1 = eval(open(code_filename, 'rb').read()) |
| 14 | 14 | data2 = None |
| 15 | 15 | output = None |
| 16 | 16 | try: |
| … |
… |
class TestRepresenterTypes(test_appliance.TestAppliance): |
| 48 | 48 | else: |
| 49 | 49 | raise |
| 50 | 50 | except: |
| 51 | | print |
| 52 | | print "OUTPUT:" |
| 53 | | print output |
| 54 | | print "NATIVES1:", data1 |
| 55 | | print "NATIVES2:", data2 |
| | 51 | print() |
| | 52 | print("OUTPUT:") |
| | 53 | print(output) |
| | 54 | print("NATIVES1:", repr(data1)) |
| | 55 | print("NATIVES2:", repr(data2)) |
| 56 | 56 | raise |
| 57 | 57 | |
| 58 | 58 | TestRepresenterTypes.add_tests('testTypes', '.data', '.code') |
-
diff --git tests/test_resolver.py tests/test_resolver.py
index a1845d8..b0693f2 100644
|
|
|
class MyLoader(Loader): |
| 9 | 9 | class MyDumper(Dumper): |
| 10 | 10 | pass |
| 11 | 11 | |
| 12 | | add_path_resolver(u'!root', [], |
| | 12 | add_path_resolver('!root', [], |
| 13 | 13 | Loader=MyLoader, Dumper=MyDumper) |
| 14 | 14 | |
| 15 | | add_path_resolver(u'!root/scalar', [], str, |
| | 15 | add_path_resolver('!root/scalar', [], str, |
| 16 | 16 | Loader=MyLoader, Dumper=MyDumper) |
| 17 | 17 | |
| 18 | | add_path_resolver(u'!root/key11/key12/*', ['key11', 'key12'], |
| | 18 | add_path_resolver('!root/key11/key12/*', ['key11', 'key12'], |
| 19 | 19 | Loader=MyLoader, Dumper=MyDumper) |
| 20 | 20 | |
| 21 | | add_path_resolver(u'!root/key21/1/*', ['key21', 1], |
| | 21 | add_path_resolver('!root/key21/1/*', ['key21', 1], |
| 22 | 22 | Loader=MyLoader, Dumper=MyDumper) |
| 23 | 23 | |
| 24 | | add_path_resolver(u'!root/key31/*/*/key14/map', ['key31', None, None, 'key14'], dict, |
| | 24 | add_path_resolver('!root/key31/*/*/key14/map', ['key31', None, None, 'key14'], dict, |
| 25 | 25 | Loader=MyLoader, Dumper=MyDumper) |
| 26 | 26 | |
| 27 | 27 | class TestResolver(test_appliance.TestAppliance): |
| … |
… |
class TestResolver(test_appliance.TestAppliance): |
| 30 | 30 | node = None |
| 31 | 31 | correct_tag = None |
| 32 | 32 | try: |
| 33 | | correct_tag = file(detect_filename, 'rb').read().strip() |
| 34 | | node = compose(file(data_filename, 'rb')) |
| | 33 | correct_tag = open(detect_filename, 'r').read().strip() |
| | 34 | node = compose(open(data_filename, 'rb')) |
| 35 | 35 | self.failUnless(isinstance(node, SequenceNode)) |
| 36 | 36 | for scalar in node.value: |
| 37 | 37 | self.failUnless(isinstance(scalar, ScalarNode)) |
| 38 | 38 | self.failUnlessEqual(scalar.tag, correct_tag) |
| 39 | 39 | except: |
| 40 | | print |
| 41 | | print "DATA:" |
| 42 | | print file(data_filename, 'rb').read() |
| 43 | | print "CORRECT_TAG:" |
| 44 | | print file(detect_filename, 'rb').read() |
| 45 | | print "ROOT NODE:", node |
| 46 | | print "SCALAR NODES:", node.value |
| | 40 | print() |
| | 41 | print("DATA:") |
| | 42 | print(open(data_filename, 'rb').read()) |
| | 43 | print("CORRECT_TAG:") |
| | 44 | print(open(detect_filename, 'rb').read()) |
| | 45 | print("ROOT NODE:", node) |
| | 46 | print("SCALAR NODES:", node.value) |
| 47 | 47 | raise |
| 48 | 48 | |
| 49 | 49 | def _testPathResolverLoader(self, test_name, data_filename, path_filename): |
| 50 | | #print serialize_all(compose_all(file(data_filename, 'rb').read(), Loader=MyLoader)) |
| 51 | | nodes1 = compose_all(file(data_filename, 'rb').read(), Loader=MyLoader) |
| 52 | | nodes2 = compose_all(file(path_filename, 'rb').read()) |
| | 50 | #print(serialize_all(compose_all(open(data_filename, 'rb').read(), Loader=MyLoader))) |
| | 51 | nodes1 = compose_all(open(data_filename, 'rb').read(), Loader=MyLoader) |
| | 52 | nodes2 = compose_all(open(path_filename, 'rb').read()) |
| 53 | 53 | for node1, node2 in zip(nodes1, nodes2): |
| 54 | 54 | self.failUnlessEqual(self._convert(node1), self._convert(node2)) |
| 55 | 55 | |
| 56 | 56 | def _testPathResolverDumper(self, test_name, data_filename, path_filename): |
| 57 | 57 | for filename in [data_filename, path_filename]: |
| 58 | | output = serialize_all(compose_all(file(filename, 'rb').read()), Dumper=MyDumper) |
| 59 | | #print output |
| | 58 | output = serialize_all(compose_all(open(filename, 'rb').read()), Dumper=MyDumper) |
| | 59 | #print(output) |
| 60 | 60 | nodes1 = compose_all(output) |
| 61 | | nodes2 = compose_all(file(data_filename, 'rb').read()) |
| | 61 | nodes2 = compose_all(open(data_filename, 'rb').read()) |
| 62 | 62 | for node1, node2 in zip(nodes1, nodes2): |
| 63 | 63 | self.failUnlessEqual(self._convert(node1), self._convert(node2)) |
| 64 | 64 | |
-
diff --git tests/test_structure.py tests/test_structure.py
index 0aef982..1919b47 100644
|
|
|
class TestStructure(test_appliance.TestAppliance): |
| 7 | 7 | |
| 8 | 8 | def _testStructure(self, test_name, data_filename, structure_filename): |
| 9 | 9 | node1 = None |
| 10 | | node2 = eval(file(structure_filename, 'rb').read()) |
| | 10 | node2 = eval(open(structure_filename, 'rb').read()) |
| 11 | 11 | try: |
| 12 | | loader = Loader(file(data_filename, 'rb')) |
| | 12 | loader = Loader(open(data_filename, 'rb')) |
| 13 | 13 | node1 = [] |
| 14 | 14 | while not loader.check_event(StreamEndEvent): |
| 15 | 15 | if not loader.check_event(StreamStartEvent, DocumentStartEvent, DocumentEndEvent): |
| … |
… |
class TestStructure(test_appliance.TestAppliance): |
| 21 | 21 | node1 = node1[0] |
| 22 | 22 | self.failUnlessEqual(node1, node2) |
| 23 | 23 | except: |
| 24 | | print |
| 25 | | print "DATA:" |
| 26 | | print file(data_filename, 'rb').read() |
| 27 | | print "NODE1:", node1 |
| 28 | | print "NODE2:", node2 |
| | 24 | print() |
| | 25 | print("DATA:") |
| | 26 | print(open(data_filename, 'rb').read()) |
| | 27 | print("NODE1:", node1) |
| | 28 | print("NODE2:", node2) |
| 29 | 29 | raise |
| 30 | 30 | |
| 31 | 31 | def _convert(self, loader): |
| … |
… |
class TestParser(test_appliance.TestAppliance): |
| 66 | 66 | events1 = None |
| 67 | 67 | events2 = None |
| 68 | 68 | try: |
| 69 | | events1 = list(parse(file(data_filename, 'rb'))) |
| 70 | | events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb'))) |
| | 69 | events1 = list(parse(open(data_filename, 'rb'))) |
| | 70 | events2 = list(test_appliance.canonical_parse(open(canonical_filename, 'rb'))) |
| 71 | 71 | self._compare(events1, events2) |
| 72 | 72 | except: |
| 73 | | print |
| 74 | | print "DATA1:" |
| 75 | | print file(data_filename, 'rb').read() |
| 76 | | print "DATA2:" |
| 77 | | print file(canonical_filename, 'rb').read() |
| 78 | | print "EVENTS1:", events1 |
| 79 | | print "EVENTS2:", events2 |
| | 73 | print() |
| | 74 | print("DATA1:") |
| | 75 | print(open(data_filename, 'rb').read()) |
| | 76 | print("DATA2:") |
| | 77 | print(open(canonical_filename, 'rb').read()) |
| | 78 | print("EVENTS1:", events1) |
| | 79 | print("EVENTS2:", events2) |
| 80 | 80 | raise |
| 81 | 81 | |
| 82 | 82 | def _compare(self, events1, events2): |
| … |
… |
class TestResolver(test_appliance.TestAppliance): |
| 103 | 103 | nodes1 = None |
| 104 | 104 | nodes2 = None |
| 105 | 105 | try: |
| 106 | | nodes1 = list(compose_all(file(data_filename, 'rb'))) |
| 107 | | nodes2 = list(test_appliance.canonical_compose_all(file(canonical_filename, 'rb'))) |
| | 106 | nodes1 = list(compose_all(open(data_filename, 'rb'))) |
| | 107 | nodes2 = list(test_appliance.canonical_compose_all(open(canonical_filename, 'rb'))) |
| 108 | 108 | self.failUnlessEqual(len(nodes1), len(nodes2)) |
| 109 | 109 | for node1, node2 in zip(nodes1, nodes2): |
| 110 | 110 | self._compare(node1, node2) |
| 111 | 111 | except: |
| 112 | | print |
| 113 | | print "DATA1:" |
| 114 | | print file(data_filename, 'rb').read() |
| 115 | | print "DATA2:" |
| 116 | | print file(canonical_filename, 'rb').read() |
| 117 | | print "NODES1:", nodes1 |
| 118 | | print "NODES2:", nodes2 |
| | 112 | print() |
| | 113 | print("DATA1:") |
| | 114 | print(open(data_filename, 'rb').read()) |
| | 115 | print("DATA2:") |
| | 116 | print(open(canonical_filename, 'rb').read()) |
| | 117 | print("NODES1:", nodes1) |
| | 118 | print("NODES2:", nodes2) |
| 119 | 119 | raise |
| 120 | 120 | |
| 121 | 121 | def _compare(self, node1, node2): |
| … |
… |
class TestResolver(test_appliance.TestAppliance): |
| 129 | 129 | self._compare(item1, item2) |
| 130 | 130 | elif isinstance(node1, MappingNode): |
| 131 | 131 | self.failUnlessEqual(len(node1.value), len(node2.value)) |
| 132 | | items1 = node1.value.items() |
| 133 | | items1.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value), |
| 134 | | (k2.tag,k2.value,v2.tag,v2.value))) |
| 135 | | items2 = node2.value.items() |
| 136 | | items2.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value), |
| 137 | | (k2.tag,k2.value,v2.tag,v2.value))) |
| | 132 | items1 = list(node1.value.items()) |
| | 133 | items1.sort(key=lambda kv: (kv[0].tag, kv[0].value, kv[1].tag, kv[1].value)) |
| | 134 | items2 = list(node2.value.items()) |
| | 135 | items2.sort(key=lambda kv: (kv[0].tag, kv[0].value, kv[1].tag, kv[1].value)) |
| 138 | 136 | for (key1, value1), (key2, value2) in zip(items1, items2): |
| 139 | 137 | self._compare(key1, key2) |
| 140 | 138 | self._compare(value1, value2) |
| … |
… |
class MyLoader(Loader): |
| 147 | 145 | |
| 148 | 146 | def construct_mapping(self, node): |
| 149 | 147 | pairs = self.construct_pairs(node) |
| 150 | | pairs.sort() |
| 151 | 148 | return pairs |
| 152 | 149 | |
| 153 | 150 | def construct_undefined(self, node): |
| 154 | 151 | return self.construct_scalar(node) |
| 155 | 152 | |
| 156 | | MyLoader.add_constructor(u'tag:yaml.org,2002:map', MyLoader.construct_mapping) |
| | 153 | MyLoader.add_constructor('tag:yaml.org,2002:map', MyLoader.construct_mapping) |
| 157 | 154 | MyLoader.add_constructor(None, MyLoader.construct_undefined) |
| 158 | 155 | |
| 159 | 156 | class MyCanonicalLoader(test_appliance.CanonicalLoader): |
| … |
… |
class MyCanonicalLoader(test_appliance.CanonicalLoader): |
| 163 | 160 | |
| 164 | 161 | def construct_mapping(self, node): |
| 165 | 162 | pairs = self.construct_pairs(node) |
| 166 | | pairs.sort() |
| 167 | 163 | return pairs |
| 168 | 164 | |
| 169 | 165 | def construct_undefined(self, node): |
| 170 | 166 | return self.construct_scalar(node) |
| 171 | 167 | |
| 172 | | MyCanonicalLoader.add_constructor(u'tag:yaml.org,2002:map', MyCanonicalLoader.construct_mapping) |
| | 168 | MyCanonicalLoader.add_constructor('tag:yaml.org,2002:map', MyCanonicalLoader.construct_mapping) |
| 173 | 169 | MyCanonicalLoader.add_constructor(None, MyCanonicalLoader.construct_undefined) |
| 174 | 170 | |
| 175 | 171 | class TestConstructor(test_appliance.TestAppliance): |
| … |
… |
class TestConstructor(test_appliance.TestAppliance): |
| 178 | 174 | data1 = None |
| 179 | 175 | data2 = None |
| 180 | 176 | try: |
| 181 | | data1 = list(load_all(file(data_filename, 'rb'), Loader=MyLoader)) |
| 182 | | data2 = list(load_all(file(canonical_filename, 'rb'), Loader=MyCanonicalLoader)) |
| | 177 | data1 = list(load_all(open(data_filename, 'rb'), Loader=MyLoader)) |
| | 178 | data2 = list(load_all(open(canonical_filename, 'rb'), Loader=MyCanonicalLoader)) |
| 183 | 179 | self.failUnlessEqual(data1, data2) |
| 184 | 180 | except: |
| 185 | | print |
| 186 | | print "DATA1:" |
| 187 | | print file(data_filename, 'rb').read() |
| 188 | | print "DATA2:" |
| 189 | | print file(canonical_filename, 'rb').read() |
| 190 | | print "NATIVES1:", data1 |
| 191 | | print "NATIVES2:", data2 |
| | 181 | print() |
| | 182 | print("DATA1:") |
| | 183 | print(open(data_filename, 'rb').read()) |
| | 184 | print("DATA2:") |
| | 185 | print(open(canonical_filename, 'rb').read()) |
| | 186 | print("NATIVES1:", data1) |
| | 187 | print("NATIVES2:", data2) |
| 192 | 188 | raise |
| 193 | 189 | |
| 194 | 190 | TestConstructor.add_tests('testConstructor', '.data', '.canonical') |
| … |
… |
class TestParserOnCanonical(test_appliance.TestAppliance): |
| 199 | 195 | events1 = None |
| 200 | 196 | events2 = None |
| 201 | 197 | try: |
| 202 | | events1 = list(parse(file(canonical_filename, 'rb'))) |
| 203 | | events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb'))) |
| | 198 | events1 = list(parse(open(canonical_filename, 'rb'))) |
| | 199 | events2 = list(test_appliance.canonical_parse(open(canonical_filename, 'rb'))) |
| 204 | 200 | self._compare(events1, events2) |
| 205 | 201 | except: |
| 206 | | print |
| 207 | | print "DATA:" |
| 208 | | print file(canonical_filename, 'rb').read() |
| 209 | | print "EVENTS1:", events1 |
| 210 | | print "EVENTS2:", events2 |
| | 202 | print() |
| | 203 | print("DATA:") |
| | 204 | print(open(canonical_filename, 'rb').read()) |
| | 205 | print("EVENTS1:", events1) |
| | 206 | print("EVENTS2:", events2) |
| 211 | 207 | raise |
| 212 | 208 | |
| 213 | 209 | def _compare(self, events1, events2): |
-
diff --git tests/test_syck.py tests/test_syck.py
index dd63056..95979c0 100644
|
|
|
class TestSyck(test_appliance.TestAppliance): |
| 7 | 7 | try: |
| 8 | 8 | syck.parse(file(data_filename, 'rb')) |
| 9 | 9 | except: |
| 10 | | print |
| 11 | | print "DATA:" |
| 12 | | print file(data_filename, 'rb').read() |
| | 10 | print() |
| | 11 | print("DATA:") |
| | 12 | print(file(data_filename, 'rb').read()) |
| 13 | 13 | raise |
| 14 | 14 | |
| 15 | 15 | def _testSyckOnCanonicalTests(self, test_name, data_filename, canonical_filename): |
| 16 | 16 | try: |
| 17 | 17 | syck.parse(file(data_filename, 'rb')) |
| 18 | 18 | except: |
| 19 | | print |
| 20 | | print "DATA:" |
| 21 | | print file(data_filename, 'rb').read() |
| | 19 | print() |
| | 20 | print("DATA:") |
| | 21 | print(file(data_filename, 'rb').read()) |
| 22 | 22 | raise |
| 23 | 23 | |
| 24 | 24 | try: |
-
diff --git tests/test_tokens.py tests/test_tokens.py
index 73d07b3..9af29c5 100644
|
|
|
class TestTokens(test_appliance.TestAppliance): |
| 47 | 47 | |
| 48 | 48 | def _testTokens(self, test_name, data_filename, tokens_filename): |
| 49 | 49 | tokens1 = None |
| 50 | | tokens2 = file(tokens_filename, 'rb').read().split() |
| | 50 | tokens2 = open(tokens_filename, 'r').read().split() |
| 51 | 51 | try: |
| 52 | 52 | tokens1 = [] |
| 53 | | for token in scan(file(data_filename, 'rb')): |
| | 53 | for token in scan(open(data_filename, 'rb')): |
| 54 | 54 | if not isinstance(token, (StreamStartToken, StreamEndToken)): |
| 55 | 55 | tokens1.append(token) |
| 56 | 56 | tokens1 = [self.replaces[t.__class__] for t in tokens1] |
| 57 | 57 | self.failUnlessEqual(tokens1, tokens2) |
| 58 | 58 | except: |
| 59 | | print |
| 60 | | print "DATA:" |
| 61 | | print file(data_filename, 'rb').read() |
| 62 | | print "TOKENS1:", tokens1 |
| 63 | | print "TOKENS2:", tokens2 |
| | 59 | print() |
| | 60 | print("DATA:") |
| | 61 | print(open(data_filename, 'rb').read()) |
| | 62 | print("TOKENS1:", tokens1) |
| | 63 | print("TOKENS2:", tokens2) |
| 64 | 64 | raise |
| 65 | 65 | |
| 66 | 66 | TestTokens.add_tests('testTokens', '.data', '.tokens') |
| … |
… |
class TestScanner(test_appliance.TestAppliance): |
| 72 | 72 | tokens = None |
| 73 | 73 | try: |
| 74 | 74 | tokens = [] |
| 75 | | for token in scan(file(filename, 'rb')): |
| | 75 | for token in scan(open(filename, 'rb')): |
| 76 | 76 | if not isinstance(token, (StreamStartToken, StreamEndToken)): |
| 77 | 77 | tokens.append(token.__class__.__name__) |
| 78 | 78 | except: |
| 79 | | print |
| 80 | | print "DATA:" |
| 81 | | print file(data_filename, 'rb').read() |
| 82 | | print "TOKENS:", tokens |
| | 79 | print() |
| | 80 | print("DATA:") |
| | 81 | print(open(data_filename, 'rb').read()) |
| | 82 | print("TOKENS:", tokens) |
| 83 | 83 | raise |
| 84 | 84 | |
| 85 | 85 | TestScanner.add_tests('testScanner', '.data', '.canonical') |
-
diff --git tests/test_yaml_ext.py tests/test_yaml_ext.py
index c5dd036..c987261 100644
|
|
|
class TestCLoader(test_appliance.TestAppliance): |
| 35 | 35 | if hasattr(token, 'value'): |
| 36 | 36 | self.failUnlessEqual(token.value, ext_token.value) |
| 37 | 37 | except: |
| 38 | | print |
| 39 | | print "DATA:" |
| 40 | | print file(data_filename, 'rb').read() |
| 41 | | print "TOKENS:", tokens |
| 42 | | print "EXT_TOKENS:", ext_tokens |
| | 38 | print() |
| | 39 | print("DATA:") |
| | 40 | print(file(data_filename, 'rb').read()) |
| | 41 | print("TOKENS:", tokens) |
| | 42 | print("EXT_TOKENS:", ext_tokens) |
| 43 | 43 | raise |
| 44 | 44 | |
| 45 | 45 | def _testCParser(self, test_name, data_filename, canonical_filename, Loader=yaml.Loader): |
| … |
… |
class TestCLoader(test_appliance.TestAppliance): |
| 49 | 49 | try: |
| 50 | 50 | for event in yaml.parse(data, Loader=yaml.CLoader): |
| 51 | 51 | ext_events.append(event) |
| 52 | | #print "EVENT:", event |
| | 52 | #print("EVENT:", event) |
| 53 | 53 | self.failUnlessEqual(len(events), len(ext_events)) |
| 54 | 54 | for event, ext_event in zip(events, ext_events): |
| 55 | 55 | self.failUnlessEqual(event.__class__, ext_event.__class__) |
| … |
… |
class TestCLoader(test_appliance.TestAppliance): |
| 68 | 68 | if hasattr(event, 'tags'): |
| 69 | 69 | self.failUnlessEqual(event.tags, ext_event.tags) |
| 70 | 70 | except: |
| 71 | | print |
| 72 | | print "DATA:" |
| 73 | | print file(data_filename, 'rb').read() |
| 74 | | print "EVENTS:", events |
| 75 | | print "EXT_EVENTS:", ext_events |
| | 71 | print() |
| | 72 | print("DATA:") |
| | 73 | print(file(data_filename, 'rb').read()) |
| | 74 | print("EVENTS:", events) |
| | 75 | print("EXT_EVENTS:", ext_events) |
| 76 | 76 | raise |
| 77 | 77 | |
| 78 | 78 | TestCLoader.add_tests('testCScanner', '.data', '.canonical') |
| … |
… |
class TestCEmitter(test_appliance.TestAppliance): |
| 108 | 108 | if hasattr(event, 'tags'): |
| 109 | 109 | self.failUnlessEqual(event.tags, ext_event.tags) |
| 110 | 110 | except: |
| 111 | | print |
| 112 | | print "DATA1:" |
| 113 | | print data1 |
| 114 | | print "DATA2:" |
| 115 | | print data2 |
| 116 | | print "EVENTS:", events |
| 117 | | print "EXT_EVENTS:", ext_events |
| | 111 | print() |
| | 112 | print("DATA1:") |
| | 113 | print(data1) |
| | 114 | print("DATA2:") |
| | 115 | print(data2) |
| | 116 | print("EVENTS:", events) |
| | 117 | print("EXT_EVENTS:", ext_events) |
| 118 | 118 | raise |
| 119 | 119 | |
| 120 | 120 | TestCEmitter.add_tests('testCEmitter', '.data', '.canonical') |