Changeset 136


Ignore:
Timestamp:
04/15/06 19:54:52 (9 years ago)
Author:
xi
Message:

Major refactoring.

Location:
pyyaml/trunk
Files:
2 added
2 deleted
27 edited

Legend:

Unmodified
Added
Removed
  • pyyaml/trunk/examples/yaml-hl/yaml_hl.py

    r119 r136  
    22 
    33import yaml, codecs, sys, optparse 
     4 
     5 
     6 
     7yaml.add_resolver(u'!Config', []) 
     8yaml.add_resolver(u'!TokensConfig', [u'tokens']) 
     9yaml.add_resolver(u'!EventsConfig', [u'events']) 
     10yaml.add_resolver(u'!StartEndConfig', [u'tokens', None]) 
     11yaml.add_resolver(u'!StartEndConfig', [u'events', None]) 
    412 
    513class YAMLHighlight: 
  • pyyaml/trunk/lib/yaml/__init__.py

    r135 r136  
    66from parser import * 
    77from composer import * 
    8 from resolver import * 
    98from constructor import * 
    109 
     
    1918from nodes import * 
    2019 
    21 from yaml_object import * 
    22  
    23 def parse(data, Reader=Reader, Scanner=Scanner, Parser=Parser): 
    24     reader = Reader(data) 
    25     scanner = Scanner(reader) 
    26     parser = Parser(scanner) 
    27     return parser 
    28  
    29 def load_all(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 
    30         Composer=Composer, Resolver=Resolver, Constructor=Constructor): 
    31     reader = Reader(data) 
    32     scanner = Scanner(reader) 
    33     parser = Parser(scanner) 
    34     composer = Composer(parser) 
    35     resolver = Resolver(composer) 
    36     constructor = Constructor(resolver) 
    37     return constructor 
    38  
    39 def safe_load_all(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 
    40         Composer=Composer, Resolver=Resolver, Constructor=SafeConstructor): 
    41     return load_all(data, Reader, Scanner, Parser, Composer, Resolver, 
    42             Constructor) 
    43  
    44 def load(data, *args, **kwds): 
    45     for document in load_all(data, *args, **kwds): 
    46         return document 
    47  
    48 def safe_load(data, *args, **kwds): 
    49     for document in safe_load_all(data, *args, **kwds): 
    50         return document 
    51  
    52 def emit(events, writer=None, Emitter=Emitter): 
    53     if writer is None: 
     20from loader import * 
     21from dumper import * 
     22 
     23def scan(stream, Loader=Loader): 
     24    """ 
     25    Scan a YAML stream and produce scanning tokens. 
     26    """ 
     27    loader = Loader(stream) 
     28    while loader.check_token(): 
     29        yield loader.get_token() 
     30 
     31def parse(stream, Loader=Loader): 
     32    """ 
     33    Parse a YAML stream and produce parsing events. 
     34    """ 
     35    loader = Loader(stream) 
     36    while loader.check_event(): 
     37        yield loader.get_event() 
     38 
     39def compose(stream, Loader=Loader): 
     40    """ 
     41    Parse the first YAML document in a stream 
     42    and produce the corresponding representation tree. 
     43    """ 
     44    loader = Loader(stream) 
     45    if loader.check_node(): 
     46        return loader.get_node() 
     47 
     48def compose_all(stream, Loader=Loader): 
     49    """ 
     50    Parse all YAML documents in a stream 
     51    and produce corresponsing representation trees. 
     52    """ 
     53    loader = Loader(stream) 
     54    while loader.check_node(): 
     55        yield loader.get_node() 
     56 
     57def load_all(stream, Loader=Loader): 
     58    """ 
     59    Parse all YAML documents in a stream 
     60    and produce corresponding Python objects. 
     61    """ 
     62    loader = Loader(stream) 
     63    while loader.check_data(): 
     64        yield loader.get_data() 
     65 
     66def load(stream, Loader=Loader): 
     67    """ 
     68    Parse the first YAML document in a stream 
     69    and produce the corresponding Python object. 
     70    """ 
     71    loader = Loader(stream) 
     72    if loader.check_data(): 
     73        return loader.get_data() 
     74 
     75def safe_load_all(stream): 
     76    """ 
     77    Parse all YAML documents in a stream 
     78    and produce corresponding Python objects. 
     79    Resolve only basic YAML tags. 
     80    """ 
     81    return load_all(stream, SafeLoader) 
     82 
     83def safe_load(stream): 
     84    """ 
     85    Parse the first YAML document in a stream 
     86    and produce the corresponding Python object. 
     87    Resolve only basic YAML tags. 
     88    """ 
     89    return load(stream, SafeLoader) 
     90 
     91def emit(events, stream=None, Dumper=Dumper, 
     92        canonical=None, indent=None, width=None, 
     93        allow_unicode=None, line_break=None): 
     94    """ 
     95    Emit YAML parsing events into a stream. 
     96    If stream is None, return the produced string instead. 
     97    """ 
     98    getvalue = None 
     99    if stream is None: 
    54100        try: 
    55101            from cStringIO import StringIO 
    56102        except ImportError: 
    57103            from StringIO import StringIO 
    58         writer = StringIO() 
    59         return_value = True 
    60     else: 
    61         return_value = False 
    62     emitter = Emitter(writer) 
     104        stream = StringIO() 
     105        getvalue = stream.getvalue 
     106    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 
     107            allow_unicode=allow_unicode, line_break=line_break) 
    63108    for event in events: 
    64         emitter.emit(event) 
    65     if return_value: 
    66         return writer.getvalue() 
    67  
    68 def dump_all(natives, writer=None, Emitter=Emitter, 
    69         Serializer=Serializer, Representer=Representer, 
    70         encoding='utf-8', line_break=None, canonical=None, 
    71         indent=None, width=None, allow_unicode=None): 
    72     if writer is None: 
     109        dumper.emit(event) 
     110    if getvalue: 
     111        return getvalue() 
     112 
     113def serialize_all(nodes, stream=None, Dumper=Dumper, 
     114        canonical=None, indent=None, width=None, 
     115        allow_unicode=None, line_break=None, 
     116        encoding='utf-8', explicit_start=None, explicit_end=None, 
     117        version=None, tags=None): 
     118    """ 
     119    Serialize a sequence of representation trees into a YAML stream. 
     120    If stream is None, return the produced string instead. 
     121    """ 
     122    getvalue = None 
     123    if stream is None: 
    73124        try: 
    74125            from cStringIO import StringIO 
    75126        except ImportError: 
    76127            from StringIO import StringIO 
    77         writer = StringIO() 
    78         return_value = True 
    79     else: 
    80         return_value = False 
    81     emitter = Emitter(writer) 
    82     serializer = Serializer(emitter, encoding=encoding, line_break=line_break, 
    83             canonical=canonical, indent=indent, width=width, 
    84             allow_unicode=allow_unicode) 
    85     representer = Representer(serializer) 
    86     for native in natives: 
    87         representer.represent(native) 
    88     representer.close() 
    89     if return_value: 
    90         return writer.getvalue() 
    91  
    92 def safe_dump_all(natives, writer=None, Emitter=Emitter, 
    93         Serializer=Serializer, Representer=SafeRepresenter, 
    94         encoding='utf-8', line_break=None, canonical=None, 
    95         indent=None, width=None, allow_unicode=None): 
    96     return dump_all(natives, writer, Emitter, Serializer, Representer, 
    97             encoding, line_break, canonical, indent, width, allow_unicode) 
    98  
    99 def dump(native, *args, **kwds): 
    100     return dump_all([native], *args, **kwds) 
    101  
    102 def safe_dump(native, *args, **kwds): 
    103     return safe_dump_all([native], *args, **kwds) 
    104  
     128        stream = StringIO() 
     129        getvalue = stream.getvalue 
     130    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 
     131            allow_unicode=allow_unicode, line_break=line_break, 
     132            encoding=encoding, version=version, tags=tags, 
     133            explicit_start=explicit_start, explicit_end=explicit_end) 
     134    dumper.open() 
     135    for node in nodes: 
     136        dumper.serialize(node) 
     137    dumper.close() 
     138    if getvalue: 
     139        return getvalue() 
     140 
     141def serialize(node, stream=None, Dumper=Dumper, **kwds): 
     142    """ 
     143    Serialize a representation tree into a YAML stream. 
     144    If stream is None, return the produced string instead. 
     145    """ 
     146    return serialize_all([node], stream, Dumper=Dumper, **kwds) 
     147 
     148def dump_all(documents, stream=None, Dumper=Dumper, 
     149        canonical=None, indent=None, width=None, 
     150        allow_unicode=None, line_break=None, 
     151        encoding='utf-8', explicit_start=None, explicit_end=None, 
     152        version=None, tags=None): 
     153    """ 
     154    Serialize a sequence of Python objects into a YAML stream. 
     155    If stream is None, return the produced string instead. 
     156    """ 
     157    getvalue = None 
     158    if stream is None: 
     159        try: 
     160            from cStringIO import StringIO 
     161        except ImportError: 
     162            from StringIO import StringIO 
     163        stream = StringIO() 
     164        getvalue = stream.getvalue 
     165    dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 
     166            allow_unicode=allow_unicode, line_break=line_break, 
     167            encoding=encoding, version=version, tags=tags, 
     168            explicit_start=explicit_start, explicit_end=explicit_end) 
     169    dumper.open() 
     170    for data in documents: 
     171        dumper.represent(data) 
     172    dumper.close() 
     173    if getvalue: 
     174        return getvalue() 
     175 
     176def dump(data, stream=None, Dumper=Dumper, **kwds): 
     177    """ 
     178    Serialize a Python object into a YAML stream. 
     179    If stream is None, return the produced string instead. 
     180    """ 
     181    return dump_all([data], stream, Dumper=Dumper, **kwds) 
     182 
     183def safe_dump_all(documents, stream=None, **kwds): 
     184    """ 
     185    Serialize a sequence of Python objects into a YAML stream. 
     186    Produce only basic YAML tags. 
     187    If stream is None, return the produced string instead. 
     188    """ 
     189    return dump_all(documents, stream, Dumper=SafeDumper, **kwds) 
     190 
     191def safe_dump(data, stream=None, **kwds): 
     192    """ 
     193    Serialize a Python object into a YAML stream. 
     194    Produce only basic YAML tags. 
     195    If stream is None, return the produced string instead. 
     196    """ 
     197    return dump_all([data], stream, Dumper=SafeDumper, **kwds) 
     198 
     199def add_detector(tag, regexp, first=None, Loader=Loader, Dumper=Dumper): 
     200    """ 
     201    Add an implicit scalar detector. 
     202    If an implicit scalar value matches the given regexp, 
     203    the corresponding tag is assigned to the scalar. 
     204    first is a sequence of possible initial characters or None. 
     205    """ 
     206    Loader.add_detector(tag, regexp, first) 
     207    Dumper.add_detector(tag, regexp, first) 
     208 
     209def add_resolver(tag, path, Loader=Loader): 
     210    """ 
     211    Add a path based resolver for the given tag. 
     212    A path is a list of keys that forms a path 
     213    to a node in the representation tree. 
     214    Keys can be string values, integers, or None. 
     215    """ 
     216    Loader.add_resolver(tag, path) 
     217 
     218def add_constructor(tag, constructor, Loader=Loader): 
     219    """ 
     220    Add a constructor for the given tag. 
     221    Constructor is a function that accepts a Loader instance 
     222    and a node object and produces the corresponding Python object. 
     223    """ 
     224    Loader.add_constructor(tag, constructor) 
     225 
     226def add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader): 
     227    """ 
     228    Add a multi-constructor for the given tag prefix. 
     229    Multi-constructor is called for a node if its tag starts with tag_prefix. 
     230    Multi-constructor accepts a Loader instance, a tag suffix, 
     231    and a node object and produces the corresponding Python object. 
     232    """ 
     233    Loader.add_multi_constructor(tag_prefix, multi_constructor) 
     234 
     235class YAMLObjectMetaclass(type): 
     236    """ 
     237    The metaclass for YAMLObject. 
     238    """ 
     239    def __init__(cls, name, bases, kwds): 
     240        super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) 
     241        if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: 
     242            cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) 
     243            cls.yaml_dumper.add_representer(cls, cls.to_yaml) 
     244 
     245class YAMLObject(object): 
     246    """ 
     247    An object that can dump itself to a YAML stream 
     248    and load itself from a YAML stream. 
     249    """ 
     250 
     251    __metaclass__ = YAMLObjectMetaclass 
     252 
     253    yaml_loader = Loader 
     254    yaml_dumper = Dumper 
     255 
     256    yaml_tag = None 
     257    yaml_flow_style = None 
     258 
     259    def from_yaml(cls, loader, node): 
     260        """ 
     261        Convert a representation node to a Python object. 
     262        """ 
     263        return loader.construct_yaml_object(node, cls) 
     264    from_yaml = classmethod(from_yaml) 
     265 
     266    def to_yaml(cls, dumper, data): 
     267        """ 
     268        Convert a Python object to a representation node. 
     269        """ 
     270        return dumper.represent_yaml_object(cls.yaml_tag, data, cls, 
     271                flow_style=cls.yaml_flow_style) 
     272    to_yaml = classmethod(to_yaml) 
     273 
  • pyyaml/trunk/lib/yaml/composer.py

    r133 r136  
    11 
    2 __all__ = ['Composer', 'ComposerError'] 
     2__all__ = ['BaseComposer', 'Composer', 'ComposerError'] 
    33 
    44from error import MarkedYAMLError 
     
    99    pass 
    1010 
    11 class Composer: 
     11class BaseComposer: 
    1212 
    13     def __init__(self, parser): 
    14         self.parser = parser 
     13    yaml_resolvers = {} 
     14 
     15    def __init__(self): 
    1516        self.all_anchors = {} 
    1617        self.complete_anchors = {} 
     18        self.resolver_tags = [] 
     19        self.resolver_paths = [] 
    1720 
    18         # Drop the STREAM-START event. 
    19         self.parser.get() 
     21    def check_node(self): 
     22        # If there are more documents available? 
     23        return not self.check_event(StreamEndEvent) 
    2024 
    21     def check(self): 
    22         # If there are more documents available? 
    23         return not self.parser.check(StreamEndEvent) 
    24  
    25     def get(self): 
     25    def get_node(self): 
    2626        # Get the root node of the next document. 
    27         if not self.parser.check(StreamEndEvent): 
     27        if not self.check_event(StreamEndEvent): 
    2828            return self.compose_document() 
    2929 
    3030    def __iter__(self): 
    3131        # Iterator protocol. 
    32         while not self.parser.check(StreamEndEvent): 
     32        while not self.check_event(StreamEndEvent): 
    3333            yield self.compose_document() 
    3434 
    3535    def compose_document(self): 
    3636 
     37        # Drop the STREAM-START event. 
     38        if self.check_event(StreamStartEvent): 
     39            self.get_event() 
     40 
    3741        # Drop the DOCUMENT-START event. 
    38         self.parser.get() 
     42        self.get_event() 
    3943 
    4044        # Compose the root node. 
    41         node = self.compose_node() 
     45        node = self.compose_node([]) 
    4246 
    4347        # Drop the DOCUMENT-END event. 
    44         self.parser.get() 
     48        self.get_event() 
    4549 
    4650        self.all_anchors = {} 
    4751        self.complete_anchors = {} 
     52        self.resolver_tags = [] 
     53        self.resolver_paths = [] 
    4854        return node 
    4955 
    50     def compose_node(self): 
    51         if self.parser.check(AliasEvent): 
    52             event = self.parser.get() 
     56    def increase_resolver_depth(self, path): 
     57        depth = len(path) 
     58        tag = None 
     59        paths = [] 
     60        if not depth: 
     61            for resolver_path in self.yaml_resolvers.keys(): 
     62                if resolver_path: 
     63                    paths.append(resolver_path) 
     64                else: 
     65                    tag = self.yaml_resolvers[resolver_path] 
     66        else: 
     67            base, index = path[-1] 
     68            if isinstance(index, ScalarNode)    \ 
     69                    and index.tag == self.DEFAULT_SCALAR_TAG: 
     70                index = index.value 
     71            elif isinstance(index, Node): 
     72                index = None 
     73            for resolver_path in self.resolver_paths[-1]: 
     74                resolver_index = resolver_path[depth-1] 
     75                if resolver_index is None or resolver_index == index: 
     76                    if len(resolver_index) > depth: 
     77                        paths.append(resolver_path) 
     78                    else: 
     79                        tag = self.yaml_resolvers[resolver_path] 
     80        self.resolver_tags.append(tag) 
     81        self.resolver_paths.append(paths) 
     82 
     83    def decrease_resolver_depth(self): 
     84        del self.resolver_tags[-1] 
     85        del self.resolver_paths[-1] 
     86 
     87    def compose_node(self, path): 
     88        if self.check_event(AliasEvent): 
     89            event = self.get_event() 
    5390            anchor = event.anchor 
    5491            if anchor not in self.all_anchors: 
     
    6299                        event.start_mark) 
    63100            return self.complete_anchors[anchor] 
    64         event = self.parser.peek() 
     101        self.increase_resolver_depth(path) 
     102        event = self.peek_event() 
    65103        anchor = event.anchor 
    66104        if anchor is not None: 
     
    70108                        "second occurence", event.start_mark) 
    71109            self.all_anchors[anchor] = event 
    72         if self.parser.check(ScalarEvent): 
    73             node = self.compose_scalar_node() 
    74         elif self.parser.check(SequenceStartEvent): 
    75             node = self.compose_sequence_node() 
    76         elif self.parser.check(MappingStartEvent): 
    77             node = self.compose_mapping_node() 
     110        if self.check_event(ScalarEvent): 
     111            node = self.compose_scalar_node(path) 
     112        elif self.check_event(SequenceStartEvent): 
     113            node = self.compose_sequence_node(path) 
     114        elif self.check_event(MappingStartEvent): 
     115            node = self.compose_mapping_node(path) 
    78116        if anchor is not None: 
    79117            self.complete_anchors[anchor] = node 
     118        self.decrease_resolver_depth() 
    80119        return node 
    81120 
    82     def compose_scalar_node(self): 
    83         event = self.parser.get() 
    84         return ScalarNode(event.tag, event.value, event.implicit, 
     121    def compose_scalar_node(self, path): 
     122        event = self.get_event() 
     123        tag = self.resolve_scalar(path, event.tag, event.implicit, event.value) 
     124        return ScalarNode(tag, event.value, 
    85125                event.start_mark, event.end_mark, style=event.style) 
    86126 
    87     def compose_sequence_node(self): 
    88         start_event = self.parser.get() 
    89         value = [] 
    90         while not self.parser.check(SequenceEndEvent): 
    91             value.append(self.compose_node()) 
    92         end_event = self.parser.get() 
    93         return SequenceNode(start_event.tag, value, 
    94                 start_event.start_mark, end_event.end_mark, 
     127    def compose_sequence_node(self, path): 
     128        start_event = self.get_event() 
     129        tag = self.resolve_sequence(path, start_event.tag) 
     130        node = SequenceNode(tag, [], 
     131                start_event.start_mark, None, 
    95132                flow_style=start_event.flow_style) 
     133        index = 0 
     134        while not self.check_event(SequenceEndEvent): 
     135            node.value.append(self.compose_node(path+[(node, index)])) 
     136            index += 1 
     137        end_event = self.get_event() 
     138        node.end_mark = end_event.end_mark 
     139        return node 
    96140 
    97     def compose_mapping_node(self): 
    98         start_event = self.parser.get() 
    99         value = {} 
    100         while not self.parser.check(MappingEndEvent): 
    101             key_event = self.parser.peek() 
    102             item_key = self.compose_node() 
    103             item_value = self.compose_node() 
    104             if item_key in value: 
     141    def compose_mapping_node(self, path): 
     142        start_event = self.get_event() 
     143        tag = self.resolve_mapping(path, start_event.tag) 
     144        node = MappingNode(tag, {}, 
     145                start_event.start_mark, None, 
     146                flow_style=start_event.flow_style) 
     147        while not self.check_event(MappingEndEvent): 
     148            key_event = self.peek_event() 
     149            item_key = self.compose_node(path+[(node, None)]) 
     150            item_value = self.compose_node(path+[(node, item_key)]) 
     151            if item_key in node.value: 
    105152                raise ComposerError("while composing a mapping", start_event.start_mark, 
    106153                        "found duplicate key", key_event.start_mark) 
    107             value[item_key] = item_value 
    108         end_event = self.parser.get() 
    109         return MappingNode(start_event.tag, value, 
    110                 start_event.start_mark, end_event.end_mark, 
    111                 flow_style=start_event.flow_style) 
     154            node.value[item_key] = item_value 
     155        end_event = self.get_event() 
     156        node.end_mark = end_event.end_mark 
     157        return node 
    112158 
     159    def resolve_scalar(self, path, tag, implicit, value): 
     160        if implicit: 
     161            tag = self.detect(value) 
     162        if tag is None and self.resolver_tags[-1]: 
     163            tag = self.resolver_tags[-1] 
     164        if tag is None or tag == u'!': 
     165            tag = self.DEFAULT_SCALAR_TAG 
     166        return tag 
     167 
     168    def resolve_sequence(self, path, tag): 
     169        if tag is None and self.resolver_tags[-1]: 
     170            tag = self.resolver_tags[-1] 
     171        if tag is None or tag == u'!': 
     172            tag = self.DEFAULT_SEQUENCE_TAG 
     173        return tag 
     174 
     175    def resolve_mapping(self, path, tag): 
     176        if tag is None and self.resolver_tags[-1]: 
     177            tag = self.resolver_tags[-1] 
     178        if tag is None or tag == u'!': 
     179            tag = self.DEFAULT_MAPPING_TAG 
     180        return tag 
     181 
     182    def add_resolver(self, tag, path): 
     183        if not 'yaml_resolvers' in cls.__dict__: 
     184            cls.yaml_resolvers = cls.yaml_resolvers.copy() 
     185        cls.yaml_resolvers[tuple(path)] = tag 
     186    add_resolver = classmethod(add_resolver) 
     187 
     188class Composer(BaseComposer): 
     189    pass 
     190 
  • pyyaml/trunk/lib/yaml/constructor.py

    r133 r136  
    55from error import * 
    66from nodes import * 
     7from composer import * 
    78 
    89try: 
     
    2223    pass 
    2324 
    24 class BaseConstructor: 
    25  
    26     def __init__(self, resolver): 
    27         self.resolver = resolver 
     25class BaseConstructor(Composer): 
     26 
     27    yaml_constructors = {} 
     28    yaml_multi_constructors = {} 
     29 
     30    def __init__(self): 
    2831        self.constructed_objects = {} 
    2932 
    30     def check(self): 
     33    def check_data(self): 
    3134        # If there are more documents available? 
    32         return self.resolver.check() 
    33  
    34     def get(self): 
     35        return self.check_node() 
     36 
     37    def get_data(self): 
    3538        # Construct and return the next document. 
    36         if self.resolver.check(): 
    37             return self.construct_document(self.resolver.get()) 
     39        if self.check_node(): 
     40            return self.construct_document(self.get_node()) 
    3841 
    3942    def __iter__(self): 
    4043        # Iterator protocol. 
    41         while self.resolver.check(): 
    42             yield self.construct_document(self.resolver.get()) 
     44        while self.check_node(): 
     45            yield self.construct_document(self.get_node()) 
    4346 
    4447    def construct_document(self, node): 
    45         native = self.construct_object(node) 
     48        data = self.construct_object(node) 
    4649        self.constructed_objects = {} 
    47         return native 
     50        return data 
    4851 
    4952    def construct_object(self, node): 
    5053        if node in self.constructed_objects: 
    5154            return self.constructed_objects[node] 
     55        constructor = None 
    5256        if node.tag in self.yaml_constructors: 
    53             native = self.yaml_constructors[node.tag](self, node) 
    54         elif None in self.yaml_constructors: 
    55             native = self.yaml_constructors[None](self, node) 
    56         elif isinstance(node, ScalarNode): 
    57             native = self.construct_scalar(node) 
    58         elif isinstance(node, SequenceNode): 
    59             native = self.construct_sequence(node) 
    60         elif isinstance(node, MappingNode): 
    61             native = self.construct_mapping(node) 
    62         self.constructed_objects[node] = native 
    63         return native 
     57            constructor = lambda node: self.yaml_constructors[node.tag](self, node) 
     58        else: 
     59            for tag_prefix in self.yaml_multi_constructors: 
     60                if node.tag.startswith(tag_prefix): 
     61                    tag_suffix = node.tag[len(tag_prefix):] 
     62                    constructor = lambda node:  \ 
     63                            self.yaml_multi_constructors[tag_prefix](self, tag_suffix, node) 
     64                break 
     65            else: 
     66                if None in self.yaml_multi_constructors: 
     67                    constructor = lambda node:  \ 
     68                            self.yaml_multi_constructors[None](self, node.tag, node) 
     69                elif None in self.yaml_constructors: 
     70                    constructor = lambda node:  \ 
     71                            self.yaml_constructors[None](self, node) 
     72                elif isinstance(node, ScalarNode): 
     73                    constructor = self.construct_scalar 
     74                elif isinstance(node, SequenceNode): 
     75                    constructor = self.construct_sequence 
     76                elif isinstance(node, MappingNode): 
     77                    constructor = self.construct_mapping 
     78        data = constructor(node) 
     79        self.constructed_objects[node] = data 
     80        return data 
    6481 
    6582    def construct_scalar(self, node): 
     
    153170    add_constructor = classmethod(add_constructor) 
    154171 
    155     yaml_constructors = {} 
     172    def add_multi_constructor(cls, tag_prefix, multi_constructor): 
     173        if not 'yaml_multi_constructors' in cls.__dict__: 
     174            cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() 
     175        cls.yaml_multi_constructors[tag_prefix] = multi_constructor 
     176    add_multi_constructor = classmethod(add_multi_constructor) 
    156177 
    157178class SafeConstructor(BaseConstructor): 
     
    328349        return self.construct_mapping(node) 
    329350 
     351    def construct_yaml_object(self, node, cls): 
     352        mapping = self.construct_mapping(node) 
     353        state = {} 
     354        for key in mapping: 
     355            state[key.replace('-', '_')] = mapping[key] 
     356        data = cls.__new__(cls) 
     357        if hasattr(data, '__setstate__'): 
     358            data.__setstate__(mapping) 
     359        else: 
     360            data.__dict__.update(mapping) 
     361        return data 
     362 
    330363    def construct_undefined(self, node): 
    331364        raise ConstructorError(None, None, 
  • pyyaml/trunk/lib/yaml/detector.py

    r133 r136  
    66class BaseDetector: 
    77 
     8    DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' 
     9    DEFAULT_SEQUENCE_TAG = u'tag:yaml.org,2002:seq' 
     10    DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' 
     11 
    812    yaml_detectors = {} 
     13 
     14    def __init__(self): 
     15        pass 
    916 
    1017    def add_detector(cls, tag, regexp, first): 
  • pyyaml/trunk/lib/yaml/emitter.py

    r133 r136  
    1212from events import * 
    1313 
     14import re 
     15 
    1416class EmitterError(YAMLError): 
    1517    pass 
     
    1820    def __init__(self, scalar, empty, multiline, 
    1921            allow_flow_plain, allow_block_plain, 
    20             allow_single_quoted, allow_double_quoted, allow_block): 
     22            allow_single_quoted, allow_double_quoted, 
     23            allow_block): 
    2124        self.scalar = scalar 
    2225        self.empty = empty 
     
    3538    } 
    3639 
    37     def __init__(self, writer): 
    38  
    39         # The writer should have the methods `write` and possibly `flush`. 
    40         self.writer = writer 
    41  
    42         # Encoding is provided by STREAM-START. 
     40    def __init__(self, stream, canonical=None, indent=None, width=None, 
     41            allow_unicode=None, line_break=None): 
     42 
     43        # The stream should have the methods `write` and possibly `flush`. 
     44        self.stream = stream 
     45 
     46        # Encoding can be overriden by STREAM-START. 
    4347        self.encoding = None 
    4448 
     
    7680 
    7781        # Formatting details. 
    78         self.canonical = False 
    79         self.allow_unicode = False 
     82        self.canonical = canonical 
     83        self.allow_unicode = allow_unicode 
     84        self.best_indent = 2 
     85        if indent and 1 < indent < 10: 
     86            self.best_indent = indent 
     87        self.best_width = 80 
     88        if width and width > self.best_indent*2: 
     89            self.best_width = width 
    8090        self.best_line_break = u'\n' 
    81         self.best_indent = 2 
    82         self.best_width = 80 
     91        if line_break in [u'\r', u'\n', u'\r\n']: 
     92            self.best_line_break = line_break 
     93 
     94        # Tag prefixes. 
    8395        self.tag_prefixes = None 
    8496 
    85         # Analyses cache. 
    86         self.anchor_text = None 
    87         self.tag_text = None 
    88         self.scalar_analysis = None 
    89         self.scalar_style = None 
     97        # Prepared anchor and tag. 
     98        self.prepared_anchor = None 
     99        self.prepared_tag = None 
     100 
     101        # Scalar analysis and style. 
     102        self.analysis = None 
     103        self.style = None 
    90104 
    91105    def emit(self, event): 
     
    140154    def expect_stream_start(self): 
    141155        if isinstance(self.event, StreamStartEvent): 
    142             self.encoding = self.event.encoding 
    143             self.canonical = self.event.canonical 
    144             self.allow_unicode = self.event.allow_unicode 
    145             if self.event.indent and self.event.indent > 1: 
    146                 self.best_indent = self.event.indent 
    147             if self.event.width and self.event.width > self.best_indent: 
    148                 self.best_width = self.event.width 
    149             if self.event.line_break in [u'\r', u'\n', u'\r\n']: 
    150                 self.best_line_break = self.event.line_break 
     156            if self.event.encoding: 
     157                self.encoding = self.event.encoding 
    151158            self.write_stream_start() 
    152159            self.state = self.expect_first_document_start 
     
    166173        if isinstance(self.event, DocumentStartEvent): 
    167174            if self.event.version: 
    168                 version_text = self.analyze_version(self.event.version) 
     175                version_text = self.prepare_version(self.event.version) 
    169176                self.write_version_directive(version_text) 
    170177            self.tag_prefixes = self.DEFAULT_TAG_PREFIXES.copy() 
     
    175182                    prefix = self.event.tags[handle] 
    176183                    self.tag_prefixes[prefix] = handle 
    177                     handle_text = self.analyze_tag_handle(handle) 
    178                     prefix_text = self.analyze_tag_prefix(prefix) 
     184                    handle_text = self.prepare_tag_handle(handle) 
     185                    prefix_text = self.prepare_tag_prefix(prefix) 
    179186                    self.write_tag_directive(handle_text, prefix_text) 
    180187            implicit = (first and not self.event.explicit and not self.canonical 
     
    200207                self.write_indicator(u'...', True) 
    201208                self.write_indent() 
     209            self.flush_stream() 
    202210            self.state = self.expect_document_start 
    203211        else: 
     
    419427        length = 0 
    420428        if isinstance(self.event, NodeEvent) and self.event.anchor is not None: 
    421             if self.anchor_text is None: 
    422                 self.anchor_text = self.analyze_anchor(self.event.anchor) 
    423             length += len(self.anchor_text) 
     429            if self.prepared_anchor is None: 
     430                self.prepared_anchor = self.prepare_anchor(self.event.anchor) 
     431            length += len(self.prepared_anchor) 
    424432        if isinstance(self.event, (ScalarEvent, CollectionStartEvent))  \ 
    425433                and self.event.tag is not None: 
    426             if self.tag_text is None: 
    427                 self.tag_text = self.analyze_tag(self.event.tag) 
    428             length += len(self.tag_text) 
     434            if self.prepared_tag is None: 
     435                self.prepared_tag = self.prepare_tag(self.event.tag) 
     436            length += len(self.prepared_tag) 
    429437        if isinstance(self.event, ScalarEvent): 
    430             if self.scalar_analysis is None: 
    431                 self.scalar_analysis = self.analyze_scalar(self.event.value) 
    432             length += len(self.scalar_analysis.scalar) 
     438            if self.analysis is None: 
     439                self.analysis = self.analyze_scalar(self.event.value) 
     440            length += len(self.analysis.scalar) 
    433441        return (length < 128 and (isinstance(self.event, AliasEvent) 
    434             or (isinstance(self.event, ScalarEvent) and not self.scalar_analysis.multiline) 
     442            or (isinstance(self.event, ScalarEvent) 
     443                    and not self.analysis.empty and not self.analysis.multiline) 
    435444            or self.check_empty_sequence() or self.check_empty_mapping())) 
    436445 
     
    439448    def process_anchor(self, indicator): 
    440449        if self.event.anchor is None: 
     450            self.prepared_anchor = None 
    441451            return 
    442         if self.anchor_text is None: 
    443             self.anchor_text = self.analyze_anchor(self.event.anchor) 
    444         if self.anchor_text: 
    445             self.write_indicator(indicator+self.anchor_text, True) 
    446         self.anchor_text = None 
     452        if self.prepared_anchor is None: 
     453            self.prepared_anchor = self.prepare_anchor(self.event.anchor) 
     454        if self.prepared_anchor: 
     455            self.write_indicator(indicator+self.prepared_anchor, True) 
     456        self.prepared_anchor = None 
    447457 
    448458    def process_tag(self): 
    449         if self.event.tag is None: 
     459        tag = self.event.tag 
     460        if isinstance(self.event, ScalarEvent): 
     461            if self.style is None: 
     462                self.style = self.choose_scalar_style() 
     463            if self.style == '': 
     464                self.prepared_tag = None 
     465                return 
     466            if self.event.implicit and not tag: 
     467                tag = u'!' 
     468                self.prepared_tag = None 
     469        if not tag: 
     470            self.prepared_tag = None 
    450471            return 
    451         if isinstance(self.event, ScalarEvent) and self.best_scalar_style() == '': 
    452             return 
    453         if self.tag_text is None: 
    454             self.tag_text = self.analyze_tag(self.event.tag) 
    455         if self.tag_text: 
    456             self.write_indicator(self.tag_text, True) 
    457         self.tag_text = None 
    458  
    459     def best_scalar_style(self): 
    460         if self.scalar_analysis is None: 
    461             self.scalar_analysis = self.analyze_scalar(self.event.value) 
    462         if self.canonical: 
     472        if self.prepared_tag is None: 
     473            self.prepared_tag = self.prepare_tag(tag) 
     474        if self.prepared_tag: 
     475            self.write_indicator(self.prepared_tag, True) 
     476        self.prepared_tag = None 
     477 
     478    def choose_scalar_style(self): 
     479        if self.analysis is None: 
     480            self.analysis = self.analyze_scalar(self.event.value) 
     481        if self.event.style == '"' or self.canonical: 
    463482            return '"' 
    464         if (self.event.implicit and not self.event.style 
    465                 and ((self.flow_level and self.scalar_analysis.allow_flow_plain) 
    466                     or (not self.flow_level and self.scalar_analysis.allow_block_plain)) 
    467                 and (len(self.scalar_analysis.scalar) > 0 
    468                     or (not self.flow_level and not self.simple_key_context))): 
    469             return '' 
    470         elif self.event.style == '\'' and self.scalar_analysis.allow_single_quoted: 
    471             return '\'' 
    472         elif self.event.style in ['|', '>'] and not self.flow_level and self.scalar_analysis.allow_block: 
    473             return self.event.style 
    474         else: 
    475             return '"' 
    476         return style 
     483        if not self.event.style and self.event.implicit: 
     484            if (not (self.simple_key_context and 
     485                    (self.analysis.empty or self.analysis.multiline)) 
     486                and (self.flow_level and self.analysis.allow_flow_plain 
     487                    or (not self.flow_level and self.analysis.allow_block_plain))): 
     488                return '' 
     489        if self.event.style and self.event.style in '|>': 
     490            if not self.flow_level and self.analysis.allow_block: 
     491                return self.event.style 
     492        if not self.event.style or self.event.style == '\'': 
     493            if (self.analysis.allow_single_quoted and 
     494                    not (self.simple_key_context and self.analysis.multiline)): 
     495                return '\'' 
     496        return '"' 
    477497 
    478498    def process_scalar(self): 
    479         if self.scalar_analysis is None: 
    480             self.scalar_analysis = self.analyze_scalar(self.event.value) 
    481         style = self.best_scalar_style() 
    482         if self.scalar_analysis.multiline and not self.simple_key_context   \ 
    483                 and style not in ['|', '>']: 
    484             self.write_indent() 
    485         if style == '"': 
    486             self.write_double_quoted(self.scalar_analysis.scalar, 
    487                     split=(not self.simple_key_context)) 
    488         elif style == '\'': 
    489             self.write_single_quoted(self.scalar_analysis.scalar, 
    490                     split=(not self.simple_key_context)) 
    491         elif style == '>': 
    492             self.write_folded(self.scalar_analysis.scalar) 
    493         elif style == '|': 
    494             self.write_literal(self.scalar_analysis.scalar) 
    495         else: 
    496             self.write_plain(self.scalar_analysis.scalar, 
    497                     split=(not self.simple_key_context)) 
    498         self.scalar_analysis = None 
     499        if self.analysis is None: 
     500            self.analysis = self.analyze_scalar(self.event.value) 
     501        if self.style is None: 
     502            self.style = self.choose_scalar_style() 
     503        split = (not self.simple_key_context) 
     504        #if self.analysis.multiline and split    \ 
     505        #        and (not self.style or self.style in '\'\"'): 
     506        #    self.write_indent() 
     507        if self.style == '"': 
     508            self.write_double_quoted(self.analysis.scalar, split) 
     509        elif self.style == '\'': 
     510            self.write_single_quoted(self.analysis.scalar, split) 
     511        elif self.style == '>': 
     512            self.write_folded(self.analysis.scalar) 
     513        elif self.style == '|': 
     514            self.write_literal(self.analysis.scalar) 
     515        else: 
     516            self.write_plain(self.analysis.scalar, split) 
     517        self.analysis = None 
     518        self.style = None 
    499519 
    500520    # Analyzers. 
    501521 
    502     def analyze_version(self, version): 
     522    def prepare_version(self, version): 
    503523        major, minor = version 
    504524        if major != 1: 
     
    506526        return u'%d.%d' % (major, minor) 
    507527 
    508     def analyze_tag_handle(self, handle): 
     528    def prepare_tag_handle(self, handle): 
    509529        if not handle: 
    510530            raise EmitterError("tag handle must not be empty") 
     
    519539        return handle 
    520540 
    521     def analyze_tag_prefix(self, prefix): 
     541    def prepare_tag_prefix(self, prefix): 
    522542        if not prefix: 
    523543            raise EmitterError("tag prefix must not be empty") 
     
    542562        return u''.join(chunks) 
    543563 
    544     def analyze_tag(self, tag): 
     564    def prepare_tag(self, tag): 
    545565        if not tag: 
    546566            raise EmitterError("tag must not be empty") 
     567        if tag == u'!': 
     568            return tag 
    547569        handle = None 
    548570        suffix = tag 
     
    575597            return u'!<%s>' % suffix_text 
    576598 
    577     def analyze_anchor(self, anchor): 
     599    def prepare_anchor(self, anchor): 
    578600        if not anchor: 
    579601            raise EmitterError("anchor must not be empty") 
     
    585607        return anchor 
    586608 
    587     def analyze_scalar(self, scalar):   # It begs for refactoring. 
     609    def analyze_scalar(self, scalar): 
     610 
     611        # Empty scalar is a special case. 
    588612        if not scalar: 
    589613            return ScalarAnalysis(scalar=scalar, empty=True, multiline=False, 
     
    591615                    allow_single_quoted=True, allow_double_quoted=True, 
    592616                    allow_block=False) 
    593         contains_block_indicator = False 
    594         contains_flow_indicator = False 
    595         contains_line_breaks = False 
    596         contains_unicode_characters = False 
    597         contains_special_characters = False 
    598         contains_inline_spaces = False          # non-space space+ non-space 
    599         contains_inline_breaks = False          # non-space break+ non-space 
    600         contains_leading_spaces = False         # ^ space+ (non-space | $) 
    601         contains_leading_breaks = False         # ^ break+ (non-space | $) 
    602         contains_trailing_spaces = False        # non-space space+ $ 
    603         contains_trailing_breaks = False        # non-space break+ $ 
    604         contains_inline_breaks_spaces = False   # non-space break+ space+ non-space 
    605         contains_mixed_breaks_spaces = False    # anything else 
     617 
     618        # Indicators and special characters. 
     619        block_indicators = False 
     620        flow_indicators = False 
     621        line_breaks = False 
     622        special_characters = False 
     623 
     624        # Whitespaces. 
     625        inline_spaces = False          # non-space space+ non-space 
     626        inline_breaks = False          # non-space break+ non-space 
     627        leading_spaces = False         # ^ space+ (non-space | $) 
     628        leading_breaks = False         # ^ break+ (non-space | $) 
     629        trailing_spaces = False        # (^ | non-space) space+ $ 
     630        trailing_breaks = False        # (^ | non-space) break+ $ 
     631        inline_breaks_spaces = False   # non-space break+ space+ non-space 
     632        mixed_breaks_spaces = False    # anything else 
     633 
     634        # Check document indicators. 
    606635        if scalar.startswith(u'---') or scalar.startswith(u'...'): 
    607             contains_block_indicator = True 
    608             contains_flow_indicator = True 
    609         first = True 
    610         last = (len(scalar) == 1) 
    611         preceeded_by_space = False 
    612         followed_by_space = (len(scalar) > 1 and 
     636            block_indicators = True 
     637            flow_indicators = True 
     638 
     639        # First character or preceded by a whitespace. 
     640        preceeded_by_space = True 
     641 
     642        # Last character or followed by a whitespace. 
     643        followed_by_space = (len(scalar) == 1 or 
    613644                scalar[1] in u'\0 \t\r\n\x85\u2028\u2029') 
    614         spaces = breaks = mixed = leading = False 
     645 
     646        # The current series of whitespaces contain plain spaces. 
     647        spaces = False 
     648 
     649        # The current series of whitespaces contain line breaks. 
     650        breaks = False 
     651 
     652        # The current series of whitespaces contain a space followed by a 
     653        # break. 
     654        mixed = False 
     655 
     656        # The current series of whitespaces start at the beginning of the 
     657        # scalar. 
     658        leading = False 
     659 
    615660        index = 0 
    616661        while index < len(scalar): 
    617662            ch = scalar[index] 
    618             if first: 
     663 
     664            # Check for indicators. 
     665 
     666            if index == 0: 
     667                # Leading indicators are special characters. 
    619668                if ch in u'#,[]{}#&*!|>\'\"%@`':  
    620                     contains_flow_indicator = True 
    621                     contains_block_indicator = True 
     669                    flow_indicators = True 
     670                    block_indicators = True 
    622671                if ch in u'?:': 
    623                     contains_flow_indicator = True 
    624                     if followed_by_space or last: 
    625                         contains_block_indicator = True 
    626                 if ch == u'-' and (followed_by_space or last): 
    627                     contains_flow_indicator = True 
    628                     contains_block_indicator = True 
     672                    flow_indicators = True 
     673                    if followed_by_space: 
     674                        block_indicators = True 
     675                if ch == u'-' and followed_by_space: 
     676                    flow_indicators = True 
     677                    block_indicators = True 
    629678            else: 
     679                # Some indicators cannot appear within a scalar as well. 
    630680                if ch in u',?[]{}': 
    631                     contains_flow_indicator = True 
     681                    flow_indicators = True 
    632682                if ch == u':': 
    633                     contains_flow_indicator = True 
    634                     if followed_by_space or last: 
    635                         contains_block_indicator = True 
    636                 if ch == u'#' and (preceeded_by_space or first): 
    637                     contains_flow_indicator = True 
    638                     contains_block_indicator = True 
     683                    flow_indicators = True 
     684                    if followed_by_space: 
     685                        block_indicators = True 
     686                if ch == u'#' and preceeded_by_space: 
     687                    flow_indicators = True 
     688                    block_indicators = True 
     689 
     690            # Check for line breaks, special, and unicode characters. 
     691 
    639692            if ch in u'\n\x85\u2028\u2029': 
    640                 contains_line_breaks = True 
     693                line_breaks = True 
    641694            if not (ch == u'\n' or u'\x20' <= ch <= u'\x7E'): 
    642                 if ch < u'\x80': 
    643                     contains_special_characters = True 
     695                if ch < u'\x80' or ch == u'\uFEFF': # '\uFEFF' is BOM. 
     696                    special_characters = True 
    644697                else: 
    645                     contains_unicode_characters = True 
    646             if ch == u' ': 
    647                 if not spaces and not breaks: 
    648                     leading = first 
    649                 spaces = True 
    650             elif ch in u'\n\x85\u2028\u2029': 
    651                 if not spaces and not breaks: 
    652                     leading = first 
    653                 breaks = True 
    654                 if spaces: 
    655                     mixed = True 
    656             if ch not in u' \n\x85\u2028\u2029': 
     698                    unicode_characters = True 
     699                    if not self.allow_unicode: 
     700                        special_characters = True 
     701 
     702            # Spaces, line breaks, and how they are mixed. State machine. 
     703 
     704            # Start or continue series of whitespaces. 
     705            if ch in u' \n\x85\u2028\u2029': 
     706                if spaces and breaks: 
     707                    if ch != u' ':      # break+ (space+ break+)    => mixed 
     708                        mixed = True 
     709                elif spaces: 
     710                    if ch != u' ':      # (space+ break+)   => mixed 
     711                        breaks = True 
     712                        mixed = True 
     713                elif breaks: 
     714                    if ch == u' ':      # break+ space+ 
     715                        spaces = True 
     716                else: 
     717                    leading = (index == 0) 
     718                    if ch == u' ':      # space+ 
     719                        spaces = True 
     720                    else:               # break+ 
     721                        breaks = True 
     722 
     723            # Series of whitespaces ended with a non-space. 
     724            elif spaces or breaks: 
    657725                if leading: 
    658726                    if spaces and breaks: 
    659                         contains_mixed_breaks_spaces = True 
     727                        mixed_breaks_spaces = True 
    660728                    elif spaces: 
    661                         contains_leading_spaces = True 
     729                        leading_spaces = True 
    662730                    elif breaks: 
    663                         contains_leading_breaks = True 
     731                        leading_breaks = True 
    664732                else: 
    665733                    if mixed: 
    666                         contains_mixed_break_spaces = True 
     734                        mixed_breaks_spaces = True 
    667735                    elif spaces and breaks: 
    668                         contains_inline_breaks_spaces = True 
     736                        inline_breaks_spaces = True 
    669737                    elif spaces: 
    670                         contains_inline_spaces = True 
     738                        inline_spaces = True 
    671739                    elif breaks: 
    672                         contains_inline_breaks = True 
     740                        inline_breaks = True 
    673741                spaces = breaks = mixed = leading = False 
    674             elif last: 
     742 
     743            # Series of whitespaces reach the end. 
     744            if (spaces or breaks) and (index == len(scalar)-1): 
    675745                if spaces and breaks: 
    676                     contains_mixed_break_spaces = True 
     746                    mixed_breaks_spaces = True 
    677747                elif spaces: 
     748                    trailing_spaces = True 
    678749                    if leading: 
    679                         contains_leading_spaces = True 
    680                     else: 
    681                         contains_trailing_spaces = True 
     750                        leading_spaces = True 
    682751                elif breaks: 
     752                    trailing_breaks = True 
    683753                    if leading: 
    684                         contains_leading_breaks = True 
    685                     else: 
    686                         contains_trailing_breaks = True 
     754                        leading_breaks = True 
     755                spaces = breaks = mixed = leading = False 
     756 
     757            # Prepare for the next character. 
    687758            index += 1 
    688             first = False 
    689             last = (index+1 == len(scalar)) 
    690759            preceeded_by_space = (ch in u'\0 \t\r\n\x85\u2028\u2029') 
    691             followed_by_space = (index+1 < len(scalar) and 
     760            followed_by_space = (index+1 >= len(scalar) or 
    692761                    scalar[index+1] in u'\0 \t\r\n\x85\u2028\u2029') 
    693         if contains_unicode_characters and not self.allow_unicode: 
    694             contains_special_characters = True 
    695         allow_flow_plain = not (contains_flow_indicator or contains_special_characters 
    696             or contains_leading_spaces or contains_leading_breaks 
    697             or contains_trailing_spaces or contains_trailing_breaks 
    698             or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 
    699         allow_block_plain = not (contains_block_indicator or contains_special_characters 
    700             or contains_leading_spaces or contains_leading_breaks 
    701             or contains_trailing_spaces or contains_trailing_breaks 
    702             or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 
    703         allow_single_quoted = not (contains_special_characters 
    704             or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 
     762 
     763        # Let's decide what styles are allowed. 
     764        allow_flow_plain = True 
     765        allow_block_plain = True 
     766        allow_single_quoted = True 
    705767        allow_double_quoted = True 
    706         allow_block = not (contains_special_characters 
    707             or contains_leading_spaces or contains_leading_breaks 
    708             or contains_trailing_spaces or contains_mixed_breaks_spaces) 
    709         return ScalarAnalysis(scalar=scalar, empty=False, multiline=contains_line_breaks, 
    710                 allow_flow_plain=allow_flow_plain, allow_block_plain=allow_block_plain, 
    711                 allow_single_quoted=allow_single_quoted, allow_double_quoted=allow_double_quoted, 
     768        allow_block = True 
     769 
     770        # Leading and trailing whitespace are bad for plain scalars. We also 
     771        # do not want to mess with leading whitespaces for block scalars. 
     772        if leading_spaces or leading_breaks or trailing_spaces: 
     773            allow_flow_plain = allow_block_plain = allow_block = False 
     774 
     775        # Trailing breaks are fine for block scalars, but unacceptable for 
     776        # plain scalars. 
     777        if trailing_breaks: 
     778            allow_flow_plain = allow_block_plain = False 
     779 
     780        # The combination of (space+ break+) is only acceptable for block 
     781        # scalars. 
     782        if inline_breaks_spaces: 
     783            allow_flow_plain = allow_block_plain = allow_single_quoted = False 
     784 
     785        # Mixed spaces and breaks, as well as special character are only 
     786        # allowed for double quoted scalars. 
     787        if mixed_breaks_spaces or special_characters: 
     788            allow_flow_plain = allow_block_plain =  \ 
     789            allow_single_quoted = allow_block = False 
     790 
     791        # We don't emit multiline plain scalars. 
     792        if line_breaks: 
     793            allow_flow_plain = allow_block_plain = False 
     794 
     795        # Flow indicators are forbidden for flow plain scalars. 
     796        if flow_indicators: 
     797            allow_flow_plain = False 
     798 
     799        # Block indicators are forbidden for block plain scalars. 
     800        if block_indicators: 
     801            allow_block_plain = False 
     802 
     803        return ScalarAnalysis(scalar=scalar, 
     804                empty=False, multiline=line_breaks, 
     805                allow_flow_plain=allow_flow_plain, 
     806                allow_block_plain=allow_block_plain, 
     807                allow_single_quoted=allow_single_quoted, 
     808                allow_double_quoted=allow_double_quoted, 
    712809                allow_block=allow_block) 
    713810 
    714811    # Writers. 
     812 
     813    def flush_stream(self): 
     814        if hasattr(self.stream, 'flush'): 
     815            self.stream.flush() 
    715816 
    716817    def write_stream_start(self): 
    717818        # Write BOM if needed. 
    718819        if self.encoding and self.encoding.startswith('utf-16'): 
    719             self.writer.write(u'\xFF\xFE'.encode(self.encoding)) 
     820            self.stream.write(u'\xFF\xFE'.encode(self.encoding)) 
    720821 
    721822    def write_stream_end(self): 
    722         if hasattr(self.writer, 'flush'): 
    723             self.writer.flush() 
     823        self.flush_stream() 
    724824 
    725825    def write_indicator(self, indicator, need_whitespace, 
     
    734834        if self.encoding: 
    735835            data = data.encode(self.encoding) 
    736         self.writer.write(data) 
     836        self.stream.write(data) 
    737837 
    738838    def write_indent(self): 
     
    747847            if self.encoding: 
    748848                data = data.encode(self.encoding) 
    749             self.writer.write(data) 
     849            self.stream.write(data) 
    750850 
    751851    def write_line_break(self, data=None): 
     
    758858        if self.encoding: 
    759859            data = data.encode(self.encoding) 
    760         self.writer.write(data) 
     860        self.stream.write(data) 
    761861 
    762862    def write_version_directive(self, version_text): 
     
    764864        if self.encoding: 
    765865            data = data.encode(self.encoding) 
    766         self.writer.write(data) 
     866        self.stream.write(data) 
    767867        self.write_line_break() 
    768868 
     
    771871        if self.encoding: 
    772872            data = data.encode(self.encoding) 
    773         self.writer.write(data) 
     873        self.stream.write(data) 
    774874        self.write_line_break() 
    775875 
    776     # Scalar writers. 
     876    # Scalar streams. 
    777877 
    778878    def write_single_quoted(self, text, split=True): 
     
    795895                        if self.encoding: 
    796896                            data = data.encode(self.encoding) 
    797                         self.writer.write(data) 
     897                        self.stream.write(data) 
    798898                    start = end 
    799899            elif breaks: 
     
    815915                        if self.encoding: 
    816916                            data = data.encode(self.encoding) 
    817                         self.writer.write(data) 
     917                        self.stream.write(data) 
    818918                        start = end 
    819919                    if ch == u'\'': 
     
    822922                        if self.encoding: 
    823923                            data = data.encode(self.encoding) 
    824                         self.writer.write(data) 
     924                        self.stream.write(data) 
    825925                        start = end + 1 
    826926            if ch is not None: 
     
    864964                    if self.encoding: 
    865965                        data = data.encode(self.encoding) 
    866                     self.writer.write(data) 
     966                    self.stream.write(data) 
    867967                    start = end 
    868968                if ch is not None: 
     
    878978                    if self.encoding: 
    879979                        data = data.encode(self.encoding) 
    880                     self.writer.write(data) 
     980                    self.stream.write(data) 
    881981                    start = end+1 
    882982            if 0 < end < len(text)-1 and (ch == u' ' or start >= end)   \ 
     
    888988                if self.encoding: 
    889989                    data = data.encode(self.encoding) 
    890                 self.writer.write(data) 
     990                self.stream.write(data) 
    891991                self.write_indent() 
    892992                self.whitespace = False 
     
    897997                    if self.encoding: 
    898998                        data = data.encode(self.encoding) 
    899                     self.writer.write(data) 
     999                    self.stream.write(data) 
    9001000            end += 1 
    9011001        self.write_indicator(u'"', False) 
     
    9481048                        if self.encoding: 
    9491049                            data = data.encode(self.encoding) 
    950                         self.writer.write(data) 
     1050                        self.stream.write(data) 
    9511051                    start = end 
    9521052            else: 
     
    9551055                    if self.encoding: 
    9561056                        data = data.encode(self.encoding) 
    957                     self.writer.write(data) 
     1057                    self.stream.write(data) 
    9581058                    if ch is None: 
    9591059                        self.write_line_break() 
     
    9891089                    if self.encoding: 
    9901090                        data = data.encode(self.encoding) 
    991                     self.writer.write(data) 
     1091                    self.stream.write(data) 
    9921092                    if ch is None: 
    9931093                        self.write_line_break() 
     
    10051105            if self.encoding: 
    10061106                data = data.encode(self.encoding) 
    1007             self.writer.write(data) 
     1107            self.stream.write(data) 
    10081108        self.writespace = False 
    10091109        self.indention = False 
     
    10261126                        if self.encoding: 
    10271127                            data = data.encode(self.encoding) 
    1028                         self.writer.write(data) 
     1128                        self.stream.write(data) 
    10291129                    start = end 
    10301130            elif breaks: 
     
    10471147                    if self.encoding: 
    10481148                        data = data.encode(self.encoding) 
    1049                     self.writer.write(data) 
     1149                    self.stream.write(data) 
    10501150                    start = end 
    10511151            if ch is not None: 
  • pyyaml/trunk/lib/yaml/error.py

    r119 r136  
    4949 
    5050    def __init__(self, context=None, context_mark=None, 
    51             problem=None, problem_mark=None): 
     51            problem=None, problem_mark=None, note=None): 
    5252        self.context = context 
    5353        self.context_mark = context_mark 
    5454        self.problem = problem 
    5555        self.problem_mark = problem_mark 
     56        self.note = note 
    5657 
    5758    def __str__(self): 
    5859        lines = [] 
    59         #for (place, mark) in [(self.context, self.context_mark), 
    60         #                        (self.problem, self.problem_mark)]: 
    61         #    if place is not None: 
    62         #        lines.append(place) 
    63         #        if mark is not None: 
    64         #            lines.append(str(mark)) 
    6560        if self.context is not None: 
    6661            lines.append(self.context) 
     
    7570        if self.problem_mark is not None: 
    7671            lines.append(str(self.problem_mark)) 
     72        if self.note is not None: 
     73            lines.append(self.note) 
    7774        return '\n'.join(lines) 
    7875 
    79  
    80  
  • pyyaml/trunk/lib/yaml/events.py

    r133 r136  
    3434 
    3535class StreamStartEvent(Event): 
    36     def __init__(self, start_mark=None, end_mark=None, 
    37             encoding=None, line_break=None, canonical=None, 
    38             indent=None, width=None, allow_unicode=None): 
     36    def __init__(self, start_mark=None, end_mark=None, encoding=None): 
    3937        self.start_mark = start_mark 
    4038        self.end_mark = end_mark 
    4139        self.encoding = encoding 
    42         self.line_break = line_break 
    43         self.canonical = canonical 
    44         self.indent = indent 
    45         self.width = width 
    46         self.allow_unicode = allow_unicode 
    4740 
    4841class StreamEndEvent(Event): 
     
    6962 
    7063class ScalarEvent(NodeEvent): 
    71     def __init__(self, anchor, tag, value, start_mark=None, end_mark=None, 
    72             implicit=None, style=None): 
     64    def __init__(self, anchor, tag, implicit, value, 
     65            start_mark=None, end_mark=None, style=None): 
    7366        self.anchor = anchor 
    7467        self.tag = tag 
     68        self.implicit = implicit 
    7569        self.value = value 
    7670        self.start_mark = start_mark 
    7771        self.end_mark = end_mark 
    78         self.implicit = implicit 
    7972        self.style = style 
    8073 
  • pyyaml/trunk/lib/yaml/nodes.py

    r133 r136  
    2424class ScalarNode(Node): 
    2525    id = 'scalar' 
    26     def __init__(self, tag, value, implicit, 
     26    def __init__(self, tag, value, 
    2727            start_mark=None, end_mark=None, style=None): 
    2828        self.tag = tag 
    2929        self.value = value 
    30         self.implicit = implicit 
    3130        self.start_mark = start_mark 
    3231        self.end_mark = end_mark 
  • pyyaml/trunk/lib/yaml/parser.py

    r132 r136  
    2525# stream ::= (BOM? implicit_document)? (BOM? explicit_document)* STREAM-END 
    2626 
    27 # Note that there is a slight deviation from the specification. We require a 
    28 # non-empty node content if ANCHOR or TAG is specified. This disallow such 
    29 # documents as 
    30 # 
    31 #   key:    !!str   # empty value 
    32 # 
    33 # This is done to prevent ambiguity in parsing tags and aliases: 
    34 # 
    35 #   {   !!perl/YAML::Parser:    value } 
    36 # 
    37 # What is it? Should it be interpreted as 
    38 #   {   ? !<tag:yaml.org,2002:perl/YAML::Parser> '' : value } 
    39 # or 
    40 #   {   ? !<tag:yaml.org,2002:perl/YAML::Parser:> value : '' } 
    41 # Since we disallow non-empty node content, tags are always followed by spaces 
    42 # or line breaks. 
    43  
    4427# FIRST sets: 
    4528# stream: { STREAM-START } 
     
    6750from tokens import * 
    6851from events import * 
     52from scanner import * 
    6953 
    7054class ParserError(MarkedYAMLError): 
     
    7256 
    7357class Parser: 
    74     # Since writing an LL(1) parser is a straightforward task, we do not give 
    75     # many comments here. 
     58    # Since writing a recursive-descendant parser is a straightforward task, we 
     59    # do not give many comments here. 
    7660    # Note that we use Python generators. If you rewrite the parser in another 
    7761    # language, you may replace all 'yield'-s with event handler calls. 
     
    8266    } 
    8367 
    84     def __init__(self, scanner): 
    85         self.scanner = scanner 
     68    def __init__(self): 
    8669        self.current_event = None 
    8770        self.yaml_version = None 
     
    8972        self.event_generator = self.parse_stream() 
    9073 
    91     def check(self, *choices): 
     74    def check_event(self, *choices): 
    9275        # Check the type of the next event. 
    9376        if self.current_event is None: 
     
    9780                pass 
    9881        if self.current_event is not None: 
     82            if not choices: 
     83                return True 
    9984            for choice in choices: 
    10085                if isinstance(self.current_event, choice): 
     
    10287        return False 
    10388 
    104     def peek(self): 
     89    def peek_event(self): 
    10590        # Get the next event. 
    10691        if self.current_event is None: 
     
    11196        return self.current_event 
    11297 
    113     def get(self): 
     98    def get_event(self): 
    11499        # Get the next event. 
    115100        if self.current_event is None: 
     
    130115 
    131116        # Parse start of stream. 
    132         token = self.scanner.get() 
     117        token = self.get_token() 
    133118        yield StreamStartEvent(token.start_mark, token.end_mark, 
    134119                encoding=token.encoding) 
    135120 
    136121        # Parse implicit document. 
    137         if not self.scanner.check(DirectiveToken, DocumentStartToken, 
     122        if not self.check_token(DirectiveToken, DocumentStartToken, 
    138123                StreamEndToken): 
    139124            self.tag_handles = self.DEFAULT_TAGS 
    140             token = self.scanner.peek() 
     125            token = self.peek_token() 
    141126            start_mark = end_mark = token.start_mark 
    142127            yield DocumentStartEvent(start_mark, end_mark, 
     
    144129            for event in self.parse_block_node(): 
    145130                yield event 
    146             token = self.scanner.peek() 
     131            token = self.peek_token() 
    147132            start_mark = end_mark = token.start_mark 
    148133            explicit = False 
    149             while self.scanner.check(DocumentEndToken): 
    150                 token = self.scanner.get() 
     134            while self.check_token(DocumentEndToken): 
     135                token = self.get_token() 
    151136                end_mark = token.end_mark 
    152137                explicit = True 
     
    155140 
    156141        # Parse explicit documents. 
    157         while not self.scanner.check(StreamEndToken): 
    158             token = self.scanner.peek() 
     142        while not self.check_token(StreamEndToken): 
     143            token = self.peek_token() 
    159144            start_mark = token.start_mark 
    160145            version, tags = self.process_directives() 
    161             if not self.scanner.check(DocumentStartToken): 
     146            if not self.check_token(DocumentStartToken): 
    162147                raise ParserError(None, None, 
    163148                        "expected '<document start>', but found %r" 
    164                         % self.scanner.peek().id, 
    165                         self.scanner.peek().start_mark) 
    166             token = self.scanner.get() 
     149                        % self.peek_token().id, 
     150                        self.peek_token().start_mark) 
     151            token = self.get_token() 
    167152            end_mark = token.end_mark 
    168153            yield DocumentStartEvent(start_mark, end_mark, 
    169154                    explicit=True, version=version, tags=tags) 
    170             if self.scanner.check(DirectiveToken, 
     155            if self.check_token(DirectiveToken, 
    171156                    DocumentStartToken, DocumentEndToken, StreamEndToken): 
    172157                yield self.process_empty_scalar(token.end_mark) 
     
    174159                for event in self.parse_block_node(): 
    175160                    yield event 
    176             token = self.scanner.peek() 
     161            token = self.peek_token() 
    177162            start_mark = end_mark = token.start_mark 
    178163            explicit = False 
    179             while self.scanner.check(DocumentEndToken): 
    180                 token = self.scanner.get() 
     164            while self.check_token(DocumentEndToken): 
     165                token = self.get_token() 
    181166                end_mark = token.end_mark 
    182167                explicit=True 
     
    185170 
    186171        # Parse end of stream. 
    187         token = self.scanner.get() 
     172        token = self.get_token() 
    188173        yield StreamEndEvent(token.start_mark, token.end_mark) 
    189174 
     
    192177        self.yaml_version = None 
    193178        self.tag_handles = {} 
    194         while self.scanner.check(DirectiveToken): 
    195             token = self.scanner.get() 
     179        while self.check_token(DirectiveToken): 
     180            token = self.get_token() 
    196181            if token.name == u'YAML': 
    197182                if self.yaml_version is not None: 
     
    238223        # block_node_or_indentless_sequence ::= ALIAS | properties? 
    239224        #                                       (block_content | indentless_block_sequence) 
    240         if self.scanner.check(AliasToken): 
    241             token = self.scanner.get() 
     225        if self.check_token(AliasToken): 
     226            token = self.get_token() 
    242227            yield AliasEvent(token.value, token.start_mark, token.end_mark) 
    243228        else: 
     
    245230            tag = None 
    246231            start_mark = end_mark = tag_mark = None 
    247             if self.scanner.check(AnchorToken): 
    248                 token = self.scanner.get() 
     232            if self.check_token(AnchorToken): 
     233                token = self.get_token() 
    249234                start_mark = token.start_mark 
    250235                end_mark = token.end_mark 
    251236                anchor = token.value 
    252                 if self.scanner.check(TagToken): 
    253                     token = self.scanner.get() 
     237                if self.check_token(TagToken): 
     238                    token = self.get_token() 
    254239                    tag_mark = token.start_mark 
    255240                    end_mark = token.end_mark 
    256241                    tag = token.value 
    257             elif self.scanner.check(TagToken): 
    258                 token = self.scanner.get() 
     242            elif self.check_token(TagToken): 
     243                token = self.get_token() 
    259244                start_mark = tag_mark = token.start_mark 
    260245                end_mark = token.end_mark 
    261246                tag = token.value 
    262                 if self.scanner.check(AnchorToken): 
    263                     token = self.scanner.get() 
     247                if self.check_token(AnchorToken): 
     248                    token = self.get_token() 
    264249                    end_mark = token.end_mark 
    265250                    anchor = token.value 
    266             if tag is not None: 
     251            if tag is not None and tag != u'!': 
    267252                handle, suffix = tag 
    268253                if handle is not None: 
     
    274259                else: 
    275260                    tag = suffix 
    276             #if tag is None: 
    277             #    if not (self.scanner.check(ScalarToken) and 
    278             #            self.scanner.peek().implicit): 
    279             #        tag = u'!' 
     261            #if tag == u'!': 
     262            #    raise ParserError("while parsing a node", start_mark, 
     263            #            "found non-specific tag '!'", tag_mark, 
     264            #            "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") 
    280265            if start_mark is None: 
    281                 start_mark = end_mark = self.scanner.peek().start_mark 
     266                start_mark = end_mark = self.peek_token().start_mark 
    282267            event = None 
    283268            collection_events = None 
    284             if indentless_sequence and self.scanner.check(BlockEntryToken): 
    285                 end_mark = self.scanner.peek().end_mark 
     269            if indentless_sequence and self.check_token(BlockEntryToken): 
     270                end_mark = self.peek_token().end_mark 
    286271                event = SequenceStartEvent(anchor, tag, start_mark, end_mark) 
    287272                collection_events = self.parse_indentless_sequence() 
    288273            else: 
    289                 if self.scanner.check(ScalarToken): 
    290                     token = self.scanner.get() 
     274                if self.check_token(ScalarToken): 
     275                    token = self.get_token() 
    291276                    end_mark = token.end_mark 
    292                     implicit = (tag is None and token.implicit) 
    293                     event = ScalarEvent(anchor, tag, token.value, 
    294                             start_mark, end_mark, 
    295                             implicit=implicit, style=token.style) 
    296                 elif self.scanner.check(FlowSequenceStartToken): 
    297                     end_mark = self.scanner.peek().end_mark 
     277                    implicit = ((tag is None or tag == u'!') and token.implicit) 
     278                    event = ScalarEvent(anchor, tag, implicit, token.value, 
     279                            start_mark, end_mark, style=token.style) 
     280                elif self.check_token(FlowSequenceStartToken): 
     281                    end_mark = self.peek_token().end_mark 
    298282                    event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 
    299283                            flow_style=True) 
    300284                    collection_events = self.parse_flow_sequence() 
    301                 elif self.scanner.check(FlowMappingStartToken): 
    302                     end_mark = self.scanner.peek().end_mark 
     285                elif self.check_token(FlowMappingStartToken): 
     286                    end_mark = self.peek_token().end_mark 
    303287                    event = MappingStartEvent(anchor, tag, start_mark, end_mark, 
    304288                            flow_style=True) 
    305289                    collection_events = self.parse_flow_mapping() 
    306                 elif block and self.scanner.check(BlockSequenceStartToken): 
    307                     end_mark = self.scanner.peek().start_mark 
     290                elif block and self.check_token(BlockSequenceStartToken): 
     291                    end_mark = self.peek_token().start_mark 
    308292                    event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 
    309293                            flow_style=False) 
    310294                    collection_events = self.parse_block_sequence() 
    311                 elif block and self.scanner.check(BlockMappingStartToken): 
    312                     end_mark = self.scanner.peek().start_mark 
     295                elif block and self.check_token(BlockMappingStartToken): 
     296                    end_mark = self.peek_token().start_mark 
    313297                    event = MappingStartEvent(anchor, tag, start_mark, end_mark, 
    314298                            flow_style=False) 
     
    317301                    # Empty scalars are allowed even if a tag or an anchor is 
    318302                    # specified. 
    319                     event = ScalarEvent(anchor, tag, u'', start_mark, end_mark, 
    320                             implicit=True) 
     303                    implicit = (tag is None or tag == u'!') 
     304                    event = ScalarEvent(anchor, tag, implicit, u'', 
     305                            start_mark, end_mark) 
    321306                else: 
    322307                    if block: 
     
    324309                    else: 
    325310                        node = 'flow' 
    326                     token = self.scanner.peek() 
     311                    token = self.peek_token() 
    327312                    raise ParserError("while scanning a %s node" % node, start_mark, 
    328313                            "expected the node content, but found %r" % token.id, 
     
    335320    def parse_block_sequence(self): 
    336321        # BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END 
    337         token = self.scanner.get() 
     322        token = self.get_token() 
    338323        start_mark = token.start_mark 
    339         while self.scanner.check(BlockEntryToken): 
    340             token = self.scanner.get() 
    341             if not self.scanner.check(BlockEntryToken, BlockEndToken): 
     324        while self.check_token(BlockEntryToken): 
     325            token = self.get_token() 
     326            if not self.check_token(BlockEntryToken, BlockEndToken): 
    342327                for event in self.parse_block_node(): 
    343328                    yield event 
    344329            else: 
    345330                yield self.process_empty_scalar(token.end_mark) 
    346         if not self.scanner.check(BlockEndToken): 
    347             token = self.scanner.peek() 
     331        if not self.check_token(BlockEndToken): 
     332            token = self.peek_token() 
    348333            raise ParserError("while scanning a block collection", start_mark, 
    349334                    "expected <block end>, but found %r" % token.id, token.start_mark) 
    350         token = self.scanner.get() 
     335        token = self.get_token() 
    351336        yield SequenceEndEvent(token.start_mark, token.end_mark) 
    352337 
    353338    def parse_indentless_sequence(self): 
    354339        # (BLOCK-ENTRY block_node?)+ 
    355         while self.scanner.check(BlockEntryToken): 
    356             token = self.scanner.get() 
    357             if not self.scanner.check(BlockEntryToken, 
     340        while self.check_token(BlockEntryToken): 
     341            token = self.get_token() 
     342            if not self.check_token(BlockEntryToken, 
    358343                    KeyToken, ValueToken, BlockEndToken): 
    359344                for event in self.parse_block_node(): 
     
    361346            else: 
    362347                yield self.process_empty_scalar(token.end_mark) 
    363         token = self.scanner.peek() 
     348        token = self.peek_token() 
    364349        yield SequenceEndEvent(token.start_mark, token.start_mark) 
    365350 
     
    369354        #   (VALUE block_node_or_indentless_sequence?)?)* 
    370355        # BLOCK-END 
    371         token = self.scanner.get() 
     356        token = self.get_token() 
    372357        start_mark = token.start_mark 
    373         while self.scanner.check(KeyToken, ValueToken): 
    374             if self.scanner.check(KeyToken): 
    375                 token = self.scanner.get() 
    376                 if not self.scanner.check(KeyToken, ValueToken, BlockEndToken): 
     358        while self.check_token(KeyToken, ValueToken): 
     359            if self.check_token(KeyToken): 
     360                token = self.get_token() 
     361                if not self.check_token(KeyToken, ValueToken, BlockEndToken): 
    377362                    for event in self.parse_block_node_or_indentless_sequence(): 
    378363                        yield event 
    379364                else: 
    380365                    yield self.process_empty_scalar(token.end_mark) 
    381             if self.scanner.check(ValueToken): 
    382                 token = self.scanner.get() 
    383                 if not self.scanner.check(KeyToken, ValueToken, BlockEndToken): 
     366            if self.check_token(ValueToken): 
     367                token = self.get_token() 
     368                if not self.check_token(KeyToken, ValueToken, BlockEndToken): 
    384369                    for event in self.parse_block_node_or_indentless_sequence(): 
    385370                        yield event 
     
    387372                    yield self.process_empty_scalar(token.end_mark) 
    388373            else: 
    389                 token = self.scanner.peek() 
     374                token = self.peek_token() 
    390375                yield self.process_empty_scalar(token.start_mark) 
    391         if not self.scanner.check(BlockEndToken): 
    392             token = self.scanner.peek() 
     376        if not self.check_token(BlockEndToken): 
     377            token = self.peek_token() 
    393378            raise ParserError("while scanning a block mapping", start_mark, 
    394379                    "expected <block end>, but found %r" % token.id, token.start_mark) 
    395         token = self.scanner.get() 
     380        token = self.get_token() 
    396381        yield MappingEndEvent(token.start_mark, token.end_mark) 
    397382 
     
    407392        # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?` 
    408393        # generate an inline mapping (set syntax). 
    409         token = self.scanner.get() 
     394        token = self.get_token() 
    410395        start_mark = token.start_mark 
    411         while not self.scanner.check(FlowSequenceEndToken): 
    412             if self.scanner.check(KeyToken): 
    413                 token = self.scanner.get() 
     396        while not self.check_token(FlowSequenceEndToken): 
     397            if self.check_token(KeyToken): 
     398                token = self.get_token() 
    414399                yield MappingStartEvent(None, None, # u'!', 
    415400                        token.start_mark, token.end_mark, 
    416401                        flow_style=True) 
    417                 if not self.scanner.check(ValueToken, 
     402                if not self.check_token(ValueToken, 
    418403                        FlowEntryToken, FlowSequenceEndToken): 
    419404                    for event in self.parse_flow_node(): 
     
    421406                else: 
    422407                    yield self.process_empty_scalar(token.end_mark) 
    423                 if self.scanner.check(ValueToken): 
    424                     token = self.scanner.get() 
    425                     if not self.scanner.check(FlowEntryToken, FlowSequenceEndToken): 
     408                if self.check_token(ValueToken): 
     409                    token = self.get_token() 
     410                    if not self.check_token(FlowEntryToken, FlowSequenceEndToken): 
    426411                        for event in self.parse_flow_node(): 
    427412                            yield event 
     
    429414                        yield self.process_empty_scalar(token.end_mark) 
    430415                else: 
    431                     token = self.scanner.peek() 
     416                    token = self.peek_token() 
    432417                    yield self.process_empty_scalar(token.start_mark) 
    433                 token = self.scanner.peek() 
     418                token = self.peek_token() 
    434419                yield MappingEndEvent(token.start_mark, token.start_mark) 
    435420            else: 
    436421                for event in self.parse_flow_node(): 
    437422                    yield event 
    438             if not self.scanner.check(FlowEntryToken, FlowSequenceEndToken): 
    439                 token = self.scanner.peek() 
     423            if not self.check_token(FlowEntryToken, FlowSequenceEndToken): 
     424                token = self.peek_token() 
    440425                raise ParserError("while scanning a flow sequence", start_mark, 
    441426                        "expected ',' or ']', but got %r" % token.id, token.start_mark) 
    442             if self.scanner.check(FlowEntryToken): 
    443                 self.scanner.get() 
    444         token = self.scanner.get() 
     427            if self.check_token(FlowEntryToken): 
     428                self.get_token() 
     429        token = self.get_token() 
    445430        yield SequenceEndEvent(token.start_mark, token.end_mark) 
    446431 
     
    451436        #                       FLOW-MAPPING-END 
    452437        # flow_mapping_entry    ::= flow_node | KEY flow_node? (VALUE flow_node?)? 
    453         token = self.scanner.get() 
     438        token = self.get_token() 
    454439        start_mark = token.start_mark 
    455         while not self.scanner.check(FlowMappingEndToken): 
    456             if self.scanner.check(KeyToken): 
    457                 token = self.scanner.get() 
    458                 if not self.scanner.check(ValueToken, 
     440        while not self.check_token(FlowMappingEndToken): 
     441            if self.check_token(KeyToken): 
     442                token = self.get_token() 
     443                if not self.check_token(ValueToken, 
    459444                        FlowEntryToken, FlowMappingEndToken): 
    460445                    for event in self.parse_flow_node(): 
     
    462447                else: 
    463448                    yield self.process_empty_scalar(token.end_mark) 
    464                 if self.scanner.check(ValueToken): 
    465                     token = self.scanner.get() 
    466                     if not self.scanner.check(FlowEntryToken, FlowMappingEndToken): 
     449                if self.check_token(ValueToken): 
     450                    token = self.get_token() 
     451                    if not self.check_token(FlowEntryToken, FlowMappingEndToken): 
    467452                        for event in self.parse_flow_node(): 
    468453                            yield event 
     
    470455                        yield self.process_empty_scalar(token.end_mark) 
    471456                else: 
    472                     token = self.scanner.peek() 
     457                    token = self.peek_token() 
    473458                    yield self.process_empty_scalar(token.start_mark) 
    474459            else: 
    475460                for event in self.parse_flow_node(): 
    476461                    yield event 
    477                 yield self.process_empty_scalar(self.scanner.peek().start_mark) 
    478             if not self.scanner.check(FlowEntryToken, FlowMappingEndToken): 
    479                 token = self.scanner.peek() 
     462                yield self.process_empty_scalar(self.peek_token().start_mark) 
     463            if not self.check_token(FlowEntryToken, FlowMappingEndToken): 
     464                token = self.peek_token() 
    480465                raise ParserError("while scanning a flow mapping", start_mark, 
    481466                        "expected ',' or '}', but got %r" % token.id, token.start_mark) 
    482             if self.scanner.check(FlowEntryToken): 
    483                 self.scanner.get() 
    484         if not self.scanner.check(FlowMappingEndToken): 
    485             token = self.scanner.peek() 
     467            if self.check_token(FlowEntryToken): 
     468                self.get_token() 
     469        if not self.check_token(FlowMappingEndToken): 
     470            token = self.peek_token() 
    486471            raise ParserError("while scanning a flow mapping", start_mark, 
    487472                    "expected '}', but found %r" % token.id, token.start_mark) 
    488         token = self.scanner.get() 
     473        token = self.get_token() 
    489474        yield MappingEndEvent(token.start_mark, token.end_mark) 
    490475 
    491476    def process_empty_scalar(self, mark): 
    492         return ScalarEvent(None, None, u'', mark, mark, 
    493                 implicit=True) 
    494  
     477        return ScalarEvent(None, None, True, u'', mark, mark) 
     478 
  • pyyaml/trunk/lib/yaml/reader.py

    r130 r136  
    9292    # Yeah, it's ugly and slow. 
    9393 
    94     def __init__(self, data): 
     94    def __init__(self, stream): 
    9595        self.name = None 
    9696        self.stream = None 
     
    105105        self.line = 0 
    106106        self.column = 0 
    107         if isinstance(data, unicode): 
     107        if isinstance(stream, unicode): 
    108108            self.name = "<unicode string>" 
    109             self.check_printable(data) 
    110             self.buffer = data+u'\0' 
    111         elif isinstance(data, str): 
     109            self.check_printable(stream) 
     110            self.buffer = stream+u'\0' 
     111        elif isinstance(stream, str): 
    112112            self.name = "<string>" 
    113             self.raw_buffer = data 
     113            self.raw_buffer = stream 
    114114            self.determine_encoding() 
    115115        else: 
    116             self.stream = data 
    117             self.name = getattr(data, 'name', "<file>") 
     116            self.stream = stream 
     117            self.name = getattr(stream, 'name', "<file>") 
    118118            self.eof = False 
    119119            self.raw_buffer = '' 
  • pyyaml/trunk/lib/yaml/representer.py

    r135 r136  
    2121    pass 
    2222 
    23 class BaseRepresenter(BaseDetector): 
    24  
    25     DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' 
    26     DEFAULT_SEQUENCE_TAG = u'tag:yaml.org,2002:seq' 
    27     DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' 
    28  
    29     def __init__(self, serializer): 
    30         self.serializer = serializer 
     23class BaseRepresenter: 
     24 
     25    yaml_representers = {} 
     26 
     27    def __init__(self): 
    3128        self.represented_objects = {} 
    3229 
    33     def close(self): 
    34         self.serializer.close() 
    35  
    36     def represent(self, native): 
    37         node = self.represent_object(native) 
    38         self.serializer.serialize(node) 
     30    def represent(self, data): 
     31        node = self.represent_object(data) 
     32        self.serialize(node) 
    3933        self.represented_objects = {} 
    4034 
    41     def represent_object(self, native): 
    42         if self.ignore_aliases(native): 
     35    def represent_object(self, data): 
     36        if self.ignore_aliases(data): 
    4337            alias_key = None 
    4438        else: 
    45             alias_key = id(native) 
     39            alias_key = id(data) 
    4640        if alias_key is not None: 
    4741            if alias_key in self.represented_objects: 
    4842                node = self.represented_objects[alias_key] 
    4943                if node is None: 
    50                     raise RepresenterError("recursive objects are not allowed: %r" % native) 
     44                    raise RepresenterError("recursive objects are not allowed: %r" % data) 
    5145                return node 
    5246            self.represented_objects[alias_key] = None 
    53         for native_type in type(native).__mro__: 
    54             if native_type in self.yaml_representers: 
    55                 node = self.yaml_representers[native_type](self, native) 
     47        for data_type in type(data).__mro__: 
     48            if data_type in self.yaml_representers: 
     49                node = self.yaml_representers[data_type](self, data) 
    5650                break 
    5751        else: 
    5852            if None in self.yaml_representers: 
    59                 node = self.yaml_representers[None](self, native) 
     53                node = self.yaml_representers[None](self, data) 
    6054            else: 
    61                 node = ScalarNode(None, unicode(native)) 
     55                node = ScalarNode(None, unicode(data)) 
    6256        if alias_key is not None: 
    6357            self.represented_objects[alias_key] = node 
    6458        return node 
    6559 
    66     def add_representer(cls, native_type, representer): 
     60    def add_representer(cls, data_type, representer): 
    6761        if not 'yaml_representers' in cls.__dict__: 
    6862            cls.yaml_representers = cls.yaml_representers.copy() 
    69         cls.yaml_representers[native_type] = representer 
     63        cls.yaml_representers[data_type] = representer 
    7064    add_representer = classmethod(add_representer) 
    7165 
    72     yaml_representers = {} 
    73  
    7466    def represent_scalar(self, tag, value, style=None): 
    75         detected_tag = self.detect(value) 
    76         if detected_tag is None: 
    77             detected_tag = self.DEFAULT_SCALAR_TAG 
    78         implicit = (tag == detected_tag) 
    79         if tag == self.DEFAULT_SCALAR_TAG: 
    80             tag = None 
    81         return ScalarNode(tag, value, implicit=implicit, style=style) 
     67        return ScalarNode(tag, value, style=style) 
    8268 
    8369    def represent_sequence(self, tag, sequence, flow_style=None): 
    84         if tag == self.DEFAULT_SEQUENCE_TAG: 
    85             tag = None 
    8670        value = [] 
    8771        for item in sequence: 
     
    9074 
    9175    def represent_mapping(self, tag, mapping, flow_style=None): 
    92         if tag == self.DEFAULT_MAPPING_TAG: 
    93             tag = None 
    9476        value = {} 
    9577        if hasattr(mapping, 'keys'): 
     
    10486        return MappingNode(tag, value, flow_style=flow_style) 
    10587 
    106     def ignore_aliases(self, native): 
     88    def ignore_aliases(self, data): 
    10789        return False 
    10890 
    109 class SafeRepresenter(Detector, BaseRepresenter): 
    110  
    111     def ignore_aliases(self, native): 
    112         if native in [None, ()]: 
     91class SafeRepresenter(BaseRepresenter): 
     92 
     93    def ignore_aliases(self, data): 
     94        if data in [None, ()]: 
    11395            return True 
    114         if isinstance(native, (str, unicode, bool, int, float)): 
     96        if isinstance(data, (str, unicode, bool, int, float)): 
    11597            return True 
    11698 
    117     def represent_none(self, native): 
     99    def represent_none(self, data): 
    118100        return self.represent_scalar(u'tag:yaml.org,2002:null', 
    119101                u'null') 
    120102 
    121     def represent_str(self, native): 
     103    def represent_str(self, data): 
    122104        encoding = None 
    123105        try: 
    124             unicode(native, 'ascii') 
     106            unicode(data, 'ascii') 
    125107            encoding = 'ascii' 
    126108        except UnicodeDecodeError: 
    127109            try: 
    128                 unicode(native, 'utf-8') 
     110                unicode(data, 'utf-8') 
    129111                encoding = 'utf-8' 
    130112            except UnicodeDecodeError: 
     
    132114        if encoding: 
    133115            return self.represent_scalar(u'tag:yaml.org,2002:str', 
    134                     unicode(native, encoding)) 
     116                    unicode(data, encoding)) 
    135117        else: 
    136118            return self.represent_scalar(u'tag:yaml.org,2002:binary', 
    137                     unicode(native.encode('base64')), style='|') 
    138  
    139     def represent_unicode(self, native): 
    140         return self.represent_scalar(u'tag:yaml.org,2002:str', native) 
    141  
    142     def represent_bool(self, native): 
    143         if native: 
     119                    unicode(data.encode('base64')), style='|') 
     120 
     121    def represent_unicode(self, data): 
     122        return self.represent_scalar(u'tag:yaml.org,2002:str', data) 
     123 
     124    def represent_bool(self, data): 
     125        if data: 
    144126            value = u'true' 
    145127        else: 
     
    147129        return self.represent_scalar(u'tag:yaml.org,2002:bool', value) 
    148130 
    149     def represent_int(self, native): 
    150         return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(native)) 
    151  
    152     def represent_long(self, native): 
    153         return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(native)) 
     131    def represent_int(self, data): 
     132        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) 
     133 
     134    def represent_long(self, data): 
     135        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) 
    154136 
    155137    inf_value = 1e300000 
    156138    nan_value = inf_value/inf_value 
    157139 
    158     def represent_float(self, native): 
    159         if native == self.inf_value: 
     140    def represent_float(self, data): 
     141        if data == self.inf_value: 
    160142            value = u'.inf' 
    161         elif native == -self.inf_value: 
     143        elif data == -self.inf_value: 
    162144            value = u'-.inf' 
    163         elif native == self.nan_value or native != native: 
     145        elif data == self.nan_value or data != data: 
    164146            value = u'.nan' 
    165147        else: 
    166             value = unicode(native) 
     148            value = unicode(data) 
    167149        return self.represent_scalar(u'tag:yaml.org,2002:float', value) 
    168150 
    169     def represent_list(self, native): 
    170         pairs = (len(native) > 0) 
    171         for item in native: 
     151    def represent_list(self, data): 
     152        pairs = (len(data) > 0) 
     153        for item in data: 
    172154            if not isinstance(item, tuple) or len(item) != 2: 
    173155                pairs = False 
    174156                break 
    175157        if not pairs: 
    176             return self.represent_sequence(u'tag:yaml.org,2002:seq', native) 
     158            return self.represent_sequence(u'tag:yaml.org,2002:seq', data) 
    177159        value = [] 
    178         for item_key, item_value in native: 
     160        for item_key, item_value in data: 
    179161            value.append(self.represent_mapping(u'tag:yaml.org,2002:map', 
    180162                [(item_key, item_value)])) 
    181163        return SequenceNode(u'tag:yaml.org,2002:pairs', value) 
    182164 
    183     def represent_dict(self, native): 
    184         return self.represent_mapping(u'tag:yaml.org,2002:map', native) 
    185  
    186     def represent_set(self, native): 
     165    def represent_dict(self, data): 
     166        return self.represent_mapping(u'tag:yaml.org,2002:map', data) 
     167 
     168    def represent_set(self, data): 
    187169        value = {} 
    188         for key in native: 
     170        for key in data: 
    189171            value[key] = None 
    190172        return self.represent_mapping(u'tag:yaml.org,2002:set', value) 
    191173 
    192     def represent_date(self, native): 
    193         value = u'%04d-%02d-%02d' % (native.year, native.month, native.day) 
     174    def represent_date(self, data): 
     175        value = u'%04d-%02d-%02d' % (data.year, data.month, data.day) 
    194176        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) 
    195177 
    196     def represent_datetime(self, native): 
     178    def represent_datetime(self, data): 
    197179        value = u'%04d-%02d-%02d %02d:%02d:%02d' \ 
    198                 % (native.year, native.month, native.day, 
    199                     native.hour, native.minute, native.second) 
    200         if native.microsecond: 
    201             value += u'.' + unicode(native.microsecond/1000000.0).split(u'.')[1] 
    202         if native.utcoffset(): 
    203             value += unicode(native.utcoffset()) 
     180                % (data.year, data.month, data.day, 
     181                    data.hour, data.minute, data.second) 
     182        if data.microsecond: 
     183            value += u'.' + unicode(data.microsecond/1000000.0).split(u'.')[1] 
     184        if data.utcoffset(): 
     185            value += unicode(data.utcoffset()) 
    204186        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) 
    205187 
    206     def represent_undefined(self, native): 
    207         raise RepresenterError("cannot represent an object: %s" % native) 
     188    def represent_yaml_object(self, tag, data, cls, flow_style=None): 
     189        if hasattr(data, '__getstate__'): 
     190            state = data.__getstate__() 
     191        else: 
     192            state = data.__dict__.copy() 
     193        mapping = state 
     194        if hasattr(state, 'keys'): 
     195            mapping = [] 
     196            keys = state.keys() 
     197            keys.sort() 
     198            for key in keys: 
     199                mapping.append((key.replace('_', '-'), state[key])) 
     200        return self.represent_mapping(tag, mapping, flow_style=flow_style) 
     201 
     202    def represent_undefined(self, data): 
     203        raise RepresenterError("cannot represent an object: %s" % data) 
    208204 
    209205SafeRepresenter.add_representer(type(None), 
  • pyyaml/trunk/lib/yaml/scanner.py

    r132 r136  
    4646class Scanner: 
    4747 
    48  
    49     def __init__(self, reader): 
     48    def __init__(self): 
    5049        """Initialize the scanner.""" 
    51         # The input stream. The Reader class do the dirty work of checking for 
    52         # BOM and converting the input data to Unicode. It also adds NUL to 
    53         # the end. 
     50        # It is assumed that Scanner and Reader will have a common descendant. 
     51        # Reader do the dirty work of checking for BOM and converting the 
     52        # input data to Unicode. It also adds NUL to the end. 
    5453        # 
    5554        # Reader supports the following methods 
    56         #   self.reader.peek(i=0)       # peek the next i-th character 
    57         #   self.reader.prefix(l=1)     # peek the next l characters 
    58         #   self.reader.forward(l=1)    # read the next l characters 
    59                                         # and move the pointer 
    60         self.reader = reader 
     55        #   self.peek(i=0)       # peek the next i-th character 
     56        #   self.prefix(l=1)     # peek the next l characters 
     57        #   self.forward(l=1)    # read the next l characters and move the pointer. 
    6158 
    6259        # Had we reached the end of the stream? 
     
    114111    # Public methods. 
    115112 
    116     def check(self, *choices): 
     113    def check_token(self, *choices): 
    117114        # Check if the next token is one of the given types. 
    118115        while self.need_more_tokens(): 
    119116            self.fetch_more_tokens() 
    120117        if self.tokens: 
     118            if not choices: 
     119                return True 
    121120            for choice in choices: 
    122121                if isinstance(self.tokens[0], choice): 
     
    124123        return False 
    125124 
    126     def peek(self): 
     125    def peek_token(self): 
    127126        # Return the next token, but do not delete if from the queue. 
    128127        while self.need_more_tokens(): 
     
    131130            return self.tokens[0] 
    132131 
    133     def get(self): 
     132    def get_token(self): 
    134133        # Return the next token. 
    135134        while self.need_more_tokens(): 
     
    172171        # Compare the current indentation and column. It may add some tokens 
    173172        # and decrease the current indentation level. 
    174         self.unwind_indent(self.reader.column) 
     173        self.unwind_indent(self.column) 
    175174 
    176175        # Peek the next character. 
    177         ch = self.reader.peek() 
     176        ch = self.peek() 
    178177 
    179178        # Is it the end of stream? 
     
    266265        raise ScannerError("while scanning for the next token", None, 
    267266                "found character %r that cannot start any token" 
    268                 % ch.encode('utf-8'), self.reader.get_mark()) 
     267                % ch.encode('utf-8'), self.get_mark()) 
    269268 
    270269    # Simple keys treatment. 
     
    294293        for level in self.possible_simple_keys.keys(): 
    295294            key = self.possible_simple_keys[level] 
    296             if key.line != self.reader.line  \ 
    297                     or self.reader.index-key.index > 1024: 
     295            if key.line != self.line  \ 
     296                    or self.index-key.index > 1024: 
    298297                if key.required: 
    299298                    raise ScannerError("while scanning a simple key", key.mark, 
    300                             "could not found expected ':'", self.reader.get_mark()) 
     299                            "could not found expected ':'", self.get_mark()) 
    301300                del self.possible_simple_keys[level] 
    302301 
     
    307306 
    308307        # Check if a simple key is required at the current position. 
    309         required = not self.flow_level and self.indent == self.reader.column 
     308        required = not self.flow_level and self.indent == self.column 
    310309 
    311310        # A simple key is required only if it is the first token in the current 
     
    318317            self.remove_possible_simple_key() 
    319318            token_number = self.tokens_taken+len(self.tokens) 
    320             index = self.reader.index 
    321             line = self.reader.line 
    322             column = self.reader.column 
    323             mark = self.reader.get_mark() 
    324319            key = SimpleKey(token_number, required, 
    325                     index, line, column, mark) 
     320                    self.index, self.line, self.column, self.get_mark()) 
    326321            self.possible_simple_keys[self.flow_level] = key 
    327322 
     
    335330            #if key.required: 
    336331            #    raise ScannerError("while scanning a simple key", key.mark, 
    337             #            "could not found expected ':'", self.reader.get_mark()) 
     332            #            "could not found expected ':'", self.get_mark()) 
    338333 
    339334    # Indentation functions. 
     
    350345        #    raise ScannerError(None, None, 
    351346        #            "invalid intendation or unclosed '[' or '{'", 
    352         #            self.reader.get_mark()) 
     347        #            self.get_mark()) 
    353348 
    354349        # In the flow context, indentation is ignored. We make the scanner less 
     
    359354        # In block context, we may need to issue the BLOCK-END tokens. 
    360355        while self.indent > column: 
    361             mark = self.reader.get_mark() 
     356            mark = self.get_mark() 
    362357            self.indent = self.indents.pop() 
    363358            self.tokens.append(BlockEndToken(mark, mark)) 
     
    378373 
    379374        # Read the token. 
    380         mark = self.reader.get_mark() 
     375        mark = self.get_mark() 
    381376         
    382377        # Add STREAM-START. 
    383378        self.tokens.append(StreamStartToken(mark, mark, 
    384             encoding=self.reader.encoding)) 
     379            encoding=self.encoding)) 
    385380         
    386381 
     
    395390 
    396391        # Read the token. 
    397         mark = self.reader.get_mark() 
     392        mark = self.get_mark() 
    398393         
    399394        # Add STREAM-END. 
    400395        self.tokens.append(StreamEndToken(mark, mark)) 
    401396 
    402         # The reader is ended. 
     397        # The steam is finished. 
    403398        self.done = True 
    404399 
     
    432427 
    433428        # Add DOCUMENT-START or DOCUMENT-END. 
    434         start_mark = self.reader.get_mark() 
    435         self.reader.forward(3) 
    436         end_mark = self.reader.get_mark() 
     429        start_mark = self.get_mark() 
     430        self.forward(3) 
     431        end_mark = self.get_mark() 
    437432        self.tokens.append(TokenClass(start_mark, end_mark)) 
    438433 
     
    455450 
    456451        # Add FLOW-SEQUENCE-START or FLOW-MAPPING-START. 
    457         start_mark = self.reader.get_mark() 
    458         self.reader.forward() 
    459         end_mark = self.reader.get_mark() 
     452        start_mark = self.get_mark() 
     453        self.forward() 
     454        end_mark = self.get_mark() 
    460455        self.tokens.append(TokenClass(start_mark, end_mark)) 
    461456 
     
    478473 
    479474        # Add FLOW-SEQUENCE-END or FLOW-MAPPING-END. 
    480         start_mark = self.reader.get_mark() 
    481         self.reader.forward() 
    482         end_mark = self.reader.get_mark() 
     475        start_mark = self.get_mark() 
     476        self.forward() 
     477        end_mark = self.get_mark() 
    483478        self.tokens.append(TokenClass(start_mark, end_mark)) 
    484479 
     
    492487 
    493488        # Add FLOW-ENTRY. 
    494         start_mark = self.reader.get_mark() 
    495         self.reader.forward() 
    496         end_mark = self.reader.get_mark() 
     489        start_mark = self.get_mark() 
     490        self.forward() 
     491        end_mark = self.get_mark() 
    497492        self.tokens.append(FlowEntryToken(start_mark, end_mark)) 
    498493 
     
    506501                raise ScannerError(None, None, 
    507502                        "sequence entries are not allowed here", 
    508                         self.reader.get_mark()) 
     503                        self.get_mark()) 
    509504 
    510505            # We may need to add BLOCK-SEQUENCE-START. 
    511             if self.add_indent(self.reader.column): 
    512                 mark = self.reader.get_mark() 
     506            if self.add_indent(self.column): 
     507                mark = self.get_mark() 
    513508                self.tokens.append(BlockSequenceStartToken(mark, mark)) 
    514509 
     
    525520 
    526521        # Add BLOCK-ENTRY. 
    527         start_mark = self.reader.get_mark() 
    528         self.reader.forward() 
    529         end_mark = self.reader.get_mark() 
     522        start_mark = self.get_mark() 
     523        self.forward() 
     524        end_mark = self.get_mark() 
    530525        self.tokens.append(BlockEntryToken(start_mark, end_mark)) 
    531526 
     
    539534                raise ScannerError(None, None, 
    540535                        "mapping keys are not allowed here", 
    541                         self.reader.get_mark()) 
     536                        self.get_mark()) 
    542537 
    543538            # We may need to add BLOCK-MAPPING-START. 
    544             if self.add_indent(self.reader.column): 
    545                 mark = self.reader.get_mark() 
     539            if self.add_indent(self.column): 
     540                mark = self.get_mark() 
    546541                self.tokens.append(BlockMappingStartToken(mark, mark)) 
    547542 
     
    553548 
    554549        # Add KEY. 
    555         start_mark = self.reader.get_mark() 
    556         self.reader.forward() 
    557         end_mark = self.reader.get_mark() 
     550        start_mark = self.get_mark() 
     551        self.forward() 
     552        end_mark = self.get_mark() 
    558553        self.tokens.append(KeyToken(start_mark, end_mark)) 
    559554 
     
    592587                    raise ScannerError(None, None, 
    593588                            "mapping values are not allowed here", 
    594                             self.reader.get_mark()) 
     589                            self.get_mark()) 
    595590 
    596591            # Simple keys are allowed after ':' in the block context. 
     
    601596 
    602597        # Add VALUE. 
    603         start_mark = self.reader.get_mark() 
    604         self.reader.forward() 
    605         end_mark = self.reader.get_mark() 
     598        start_mark = self.get_mark() 
     599        self.forward() 
     600        end_mark = self.get_mark() 
    606601        self.tokens.append(ValueToken(start_mark, end_mark)) 
    607602 
     
    692687        # DIRECTIVE:        ^ '%' ... 
    693688        # The '%' indicator is already checked. 
    694         if self.reader.column == 0: 
     689        if self.column == 0: 
    695690            return True 
    696691 
     
    698693 
    699694        # DOCUMENT-START:   ^ '---' (' '|'\n') 
    700         if self.reader.column == 0: 
    701             if self.reader.prefix(3) == u'---'  \ 
    702                     and self.reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
     695        if self.column == 0: 
     696            if self.prefix(3) == u'---'  \ 
     697                    and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
    703698                return True 
    704699 
     
    706701 
    707702        # DOCUMENT-END:     ^ '...' (' '|'\n') 
    708         if self.reader.column == 0: 
    709             prefix = self.reader.peek(4) 
    710             if self.reader.prefix(3) == u'...'  \ 
    711                     and self.reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
     703        if self.column == 0: 
     704            prefix = self.peek(4) 
     705            if self.prefix(3) == u'...'  \ 
     706                    and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
    712707                return True 
    713708 
     
    715710 
    716711        # BLOCK-ENTRY:      '-' (' '|'\n') 
    717         return self.reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
     712        return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
    718713 
    719714    def check_key(self): 
     
    725720        # KEY(block context):   '?' (' '|'\n') 
    726721        else: 
    727             return self.reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
     722            return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
    728723 
    729724    def check_value(self): 
     
    735730        # VALUE(block context): ':' (' '|'\n') 
    736731        else: 
    737             return self.reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
     732            return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
    738733 
    739734    def check_plain(self): 
     
    751746        # '-' character) because we want the flow context to be space 
    752747        # independent. 
    753         ch = self.reader.peek() 
     748        ch = self.peek() 
    754749        return ch not in u'\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`'  \ 
    755                 or (self.reader.peek(1) not in u'\0 \t\r\n\x85\u2028\u2029' 
     750                or (self.peek(1) not in u'\0 \t\r\n\x85\u2028\u2029' 
    756751                        and (ch == u'-' or (not self.flow_level and ch in u'?:'))) 
    757752 
     
    778773        # Scanners for block, flow, and plain scalars need to be modified. 
    779774 
    780         if self.reader.index == 0 and self.reader.peek() == u'\uFEFF': 
    781             self.reader.forward() 
     775        if self.index == 0 and self.peek() == u'\uFEFF': 
     776            self.forward() 
    782777        found = False 
    783778        while not found: 
    784             while self.reader.peek() == u' ': 
    785                 self.reader.forward() 
    786             if self.reader.peek() == u'#': 
    787                 while self.reader.peek() not in u'\0\r\n\x85\u2028\u2029': 
    788                     self.reader.forward() 
     779            while self.peek() == u' ': 
     780                self.forward() 
     781            if self.peek() == u'#': 
     782                while self.peek() not in u'\0\r\n\x85\u2028\u2029': 
     783                    self.forward() 
    789784            if self.scan_line_break(): 
    790785                if not self.flow_level: 
     
    795790    def scan_directive(self): 
    796791        # See the specification for details. 
    797         start_mark = self.reader.get_mark() 
    798         self.reader.forward() 
     792        start_mark = self.get_mark() 
     793        self.forward() 
    799794        name = self.scan_directive_name(start_mark) 
    800795        value = None 
    801796        if name == u'YAML': 
    802797            value = self.scan_yaml_directive_value(start_mark) 
    803             end_mark = self.reader.get_mark() 
     798            end_mark = self.get_mark() 
    804799        elif name == u'TAG': 
    805800            value = self.scan_tag_directive_value(start_mark) 
    806             end_mark = self.reader.get_mark() 
     801            end_mark = self.get_mark() 
    807802        else: 
    808             end_mark = self.reader.get_mark() 
    809             while self.reader.peek() not in u'\0\r\n\x85\u2028\u2029': 
    810                 self.reader.forward() 
     803            end_mark = self.get_mark() 
     804            while self.peek() not in u'\0\r\n\x85\u2028\u2029': 
     805                self.forward() 
    811806        self.scan_directive_ignored_line(start_mark) 
    812807        return DirectiveToken(name, value, start_mark, end_mark) 
     
    815810        # See the specification for details. 
    816811        length = 0 
    817         ch = self.reader.peek(length) 
     812        ch = self.peek(length) 
    818813        while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z'  \ 
    819814                or ch in u'-_': 
    820815            length += 1 
    821             ch = self.reader.peek(length) 
     816            ch = self.peek(length) 
    822817        if not length: 
    823818            raise ScannerError("while scanning a directive", start_mark, 
    824819                    "expected alphabetic or numeric character, but found %r" 
    825                     % ch.encode('utf-8'), self.reader.get_mark()) 
    826         value = self.reader.prefix(length) 
    827         self.reader.forward(length) 
    828         ch = self.reader.peek() 
     820                    % ch.encode('utf-8'), self.get_mark()) 
     821        value = self.prefix(length) 
     822        self.forward(length) 
     823        ch = self.peek() 
    829824        if ch not in u'\0 \r\n\x85\u2028\u2029': 
    830825            raise ScannerError("while scanning a directive", start_mark, 
    831826                    "expected alphabetic or numeric character, but found %r" 
    832                     % ch.encode('utf-8'), self.reader.get_mark()) 
     827                    % ch.encode('utf-8'), self.get_mark()) 
    833828        return value 
    834829 
    835830    def scan_yaml_directive_value(self, start_mark): 
    836831        # See the specification for details. 
    837         while self.reader.peek() == u' ': 
    838             self.reader.forward() 
     832        while self.peek() == u' ': 
     833            self.forward() 
    839834        major = self.scan_yaml_directive_number(start_mark) 
    840         if self.reader.peek() != '.': 
     835        if self.peek() != '.': 
    841836            raise ScannerError("while scanning a directive", start_mark, 
    842837                    "expected a digit or '.', but found %r" 
    843                     % self.reader.peek().encode('utf-8'), 
    844                     self.reader.get_mark()) 
    845         self.reader.forward() 
     838                    % self.peek().encode('utf-8'), 
     839                    self.get_mark()) 
     840        self.forward() 
    846841        minor = self.scan_yaml_directive_number(start_mark) 
    847         if self.reader.peek() not in u'\0 \r\n\x85\u2028\u2029': 
     842        if self.peek() not in u'\0 \r\n\x85\u2028\u2029': 
    848843            raise ScannerError("while scanning a directive", start_mark, 
    849844                    "expected a digit or ' ', but found %r" 
    850                     % self.reader.peek().encode('utf-8'), 
    851                     self.reader.get_mark()) 
     845                    % self.peek().encode('utf-8'), 
     846                    self.get_mark()) 
    852847        return (major, minor) 
    853848 
    854849    def scan_yaml_directive_number(self, start_mark): 
    855850        # See the specification for details. 
    856         ch = self.reader.peek() 
     851        ch = self.peek() 
    857852        if not (u'0' <= ch <= '9'): 
    858853            raise ScannerError("while scanning a directive", start_mark, 
    859854                    "expected a digit, but found %r" % ch.encode('utf-8'), 
    860                     self.reader.get_mark()) 
     855                    self.get_mark()) 
    861856        length = 0 
    862         while u'0' <= self.reader.peek(length) <= u'9': 
     857        while u'0' <= self.peek(length) <= u'9': 
    863858            length += 1 
    864         value = int(self.reader.prefix(length)) 
    865         self.reader.forward(length) 
     859        value = int(self.prefix(length)) 
     860        self.forward(length) 
    866861        return value 
    867862 
    868863    def scan_tag_directive_value(self, start_mark): 
    869864        # See the specification for details. 
    870         while self.reader.peek() == u' ': 
    871             self.reader.forward() 
     865        while self.peek() == u' ': 
     866            self.forward() 
    872867        handle = self.scan_tag_directive_handle(start_mark) 
    873         while self.reader.peek() == u' ': 
    874             self.reader.forward() 
     868        while self.peek() == u' ': 
     869            self.forward() 
    875870        prefix = self.scan_tag_directive_prefix(start_mark) 
    876871        return (handle, prefix) 
     
    879874        # See the specification for details. 
    880875        value = self.scan_tag_handle('directive', start_mark) 
    881         ch = self.reader.peek() 
     876        ch = self.peek() 
    882877        if ch != u' ': 
    883878            raise ScannerError("while scanning a directive", start_mark, 
    884879                    "expected ' ', but found %r" % ch.encode('utf-8'), 
    885                     self.reader.get_mark()) 
     880                    self.get_mark()) 
    886881        return value 
    887882 
     
    889884        # See the specification for details. 
    890885        value = self.scan_tag_uri('directive', start_mark) 
    891         ch = self.reader.peek() 
     886        ch = self.peek() 
    892887        if ch not in u'\0 \r\n\x85\u2028\u2029': 
    893888            raise ScannerError("while scanning a directive", start_mark, 
    894889                    "expected ' ', but found %r" % ch.encode('utf-8'), 
    895                     self.reader.get_mark()) 
     890                    self.get_mark()) 
    896891        return value 
    897892 
    898893    def scan_directive_ignored_line(self, start_mark): 
    899894        # See the specification for details. 
    900         while self.reader.peek() == u' ': 
    901             self.reader.forward() 
    902         if self.reader.peek() == u'#': 
    903             while self.reader.peek() not in u'\0\r\n\x85\u2028\u2029': 
    904                 self.reader.forward() 
    905         ch = self.reader.peek() 
     895        while self.peek() == u' ': 
     896            self.forward() 
     897        if self.peek() == u'#': 
     898            while self.peek() not in u'\0\r\n\x85\u2028\u2029': 
     899                self.forward() 
     900        ch = self.peek() 
    906901        if ch not in u'\0\r\n\x85\u2028\u2029': 
    907902            raise ScannerError("while scanning a directive", start_mark, 
    908903                    "expected a comment or a line break, but found %r" 
    909                         % ch.encode('utf-8'), self.reader.get_mark()) 
     904                        % ch.encode('utf-8'), self.get_mark()) 
    910905        self.scan_line_break() 
    911906 
     
    919914        #   [ *alias , "value" ] 
    920915        # Therefore we restrict aliases to numbers and ASCII letters. 
    921         start_mark = self.reader.get_mark() 
    922         indicator = self.reader.peek() 
     916        start_mark = self.get_mark() 
     917        indicator = self.peek() 
    923918        if indicator == '*': 
    924919            name = 'alias' 
    925920        else: 
    926921            name = 'anchor' 
    927         self.reader.forward() 
     922        self.forward() 
    928923        length = 0 
    929         ch = self.reader.peek(length) 
     924        ch = self.peek(length) 
    930925        while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z'  \ 
    931926                or ch in u'-_': 
    932927            length += 1 
    933             ch = self.reader.peek(length) 
     928            ch = self.peek(length) 
    934929        if not length: 
    935930            raise ScannerError("while scanning an %s" % name, start_mark, 
    936931                    "expected alphabetic or numeric character, but found %r" 
    937                     % ch.encode('utf-8'), self.reader.get_mark()) 
    938         value = self.reader.prefix(length) 
    939         self.reader.forward(length) 
    940         ch = self.reader.peek() 
     932                    % ch.encode('utf-8'), self.get_mark()) 
     933        value = self.prefix(length) 
     934        self.forward(length) 
     935        ch = self.peek() 
    941936        if ch not in u'\0 \t\r\n\x85\u2028\u2029?:,]}%@`': 
    942937            raise ScannerError("while scanning an %s" % name, start_mark, 
    943938                    "expected alphabetic or numeric character, but found %r" 
    944                     % ch.encode('utf-8'), self.reader.get_mark()) 
    945         end_mark = self.reader.get_mark() 
     939                    % ch.encode('utf-8'), self.get_mark()) 
     940        end_mark = self.get_mark() 
    946941        return TokenClass(value, start_mark, end_mark) 
    947942 
    948943    def scan_tag(self): 
    949944        # See the specification for details. 
    950         start_mark = self.reader.get_mark() 
    951         ch = self.reader.peek(1) 
     945        start_mark = self.get_mark() 
     946        ch = self.peek(1) 
    952947        if ch == u'<': 
    953948            handle = None 
    954             self.reader.forward(2) 
     949            self.forward(2) 
    955950            suffix = self.scan_tag_uri('tag', start_mark) 
    956             if self.reader.peek() != u'>': 
     951            if self.peek() != u'>': 
    957952                raise ScannerError("while parsing a tag", start_mark, 
    958                         "expected '>', but found %r" % self.reader.peek().encode('utf-8'), 
    959                         self.reader.get_mark()) 
    960             self.reader.forward() 
     953                        "expected '>', but found %r" % self.peek().encode('utf-8'), 
     954                        self.get_mark()) 
     955            self.forward() 
    961956        elif ch in u'\0 \t\r\n\x85\u2028\u2029': 
    962957            handle = None 
    963958            suffix = u'!' 
    964             self.reader.forward() 
     959            self.forward() 
    965960        else: 
    966961            length = 1 
     
    971966                    break 
    972967                length += 1 
    973                 ch = self.reader.peek(length) 
     968                ch = self.peek(length) 
    974969            handle = u'!' 
    975970            if use_handle: 
     
    977972            else: 
    978973                handle = u'!' 
    979                 self.reader.forward() 
     974                self.forward() 
    980975            suffix = self.scan_tag_uri('tag', start_mark) 
    981         ch = self.reader.peek() 
     976        ch = self.peek() 
    982977        if ch not in u'\0 \r\n\x85\u2028\u2029': 
    983978            raise ScannerError("while scanning a tag", start_mark, 
    984979                    "expected ' ', but found %r" % ch.encode('utf-8'), 
    985                     self.reader.get_mark()) 
     980                    self.get_mark()) 
    986981        value = (handle, suffix) 
    987         end_mark = self.reader.get_mark() 
     982        end_mark = self.get_mark() 
    988983        return TagToken(value, start_mark, end_mark) 
    989984 
     
    997992 
    998993        chunks = [] 
    999         start_mark = self.reader.get_mark() 
     994        start_mark = self.get_mark() 
    1000995 
    1001996        # Scan the header. 
    1002         self.reader.forward() 
     997        self.forward() 
    1003998        chomping, increment = self.scan_block_scalar_indicators(start_mark) 
    1004999        self.scan_block_scalar_ignored_line(start_mark) 
     
    10171012 
    10181013        # Scan the inner part of the block scalar. 
    1019         while self.reader.column == indent and self.reader.peek() != u'\0': 
     1014        while self.column == indent and self.peek() != u'\0': 
    10201015            chunks.extend(breaks) 
    1021             leading_non_space = self.reader.peek() not in u' \t' 
     1016            leading_non_space = self.peek() not in u' \t' 
    10221017            length = 0 
    1023             while self.reader.peek(length) not in u'\0\r\n\x85\u2028\u2029': 
     1018            while self.peek(length) not in u'\0\r\n\x85\u2028\u2029': 
    10241019                length += 1 
    1025             chunks.append(self.reader.prefix(length)) 
    1026             self.reader.forward(length) 
     1020            chunks.append(self.prefix(length)) 
     1021            self.forward(length) 
    10271022            line_break = self.scan_line_break() 
    10281023            breaks, end_mark = self.scan_block_scalar_breaks(indent) 
    1029             if self.reader.column == indent and self.reader.peek() != u'\0': 
     1024            if self.column == indent and self.peek() != u'\0': 
    10301025 
    10311026                # Unfortunately, folding rules are ambiguous. 
     
    10341029                 
    10351030                if folded and line_break == u'\n'   \ 
    1036                         and leading_non_space and self.reader.peek() not in u' \t': 
     1031                        and leading_non_space and self.peek() not in u' \t': 
    10371032                    if not breaks: 
    10381033                        chunks.append(u' ') 
     
    10451040                #if folded and line_break == u'\n': 
    10461041                #    if not breaks: 
    1047                 #        if self.reader.peek() not in ' \t': 
     1042                #        if self.peek() not in ' \t': 
    10481043                #            chunks.append(u' ') 
    10491044                #        else: 
     
    10681063        chomping = None 
    10691064        increment = None 
    1070         ch = self.reader.peek() 
     1065        ch = self.peek() 
    10711066        if ch in u'+-': 
    10721067            if ch == '+': 
     
    10741069            else: 
    10751070                chomping = False 
    1076             self.reader.forward() 
    1077             ch = self.reader.peek() 
     1071            self.forward() 
     1072            ch = self.peek() 
    10781073            if ch in u'0123456789': 
    10791074                increment = int(ch) 
     
    10811076                    raise ScannerError("while scanning a block scalar", start_mark, 
    10821077                            "expected indentation indicator in the range 1-9, but found 0", 
    1083                             self.reader.get_mark()) 
    1084                 self.reader.forward() 
     1078                            self.get_mark()) 
     1079                self.forward() 
    10851080        elif ch in u'0123456789': 
    10861081            increment = int(ch) 
     
    10881083                raise ScannerError("while scanning a block scalar", start_mark, 
    10891084                        "expected indentation indicator in the range 1-9, but found 0", 
    1090                         self.reader.get_mark()) 
    1091             self.reader.forward() 
    1092             ch = self.reader.peek() 
     1085                        self.get_mark()) 
     1086            self.forward() 
     1087            ch = self.peek() 
    10931088            if ch in u'+-': 
    10941089                if ch == '+': 
     
    10961091                else: 
    10971092                    chomping = False 
    1098                 self.reader.forward() 
    1099         ch = self.reader.peek() 
     1093                self.forward() 
     1094        ch = self.peek() 
    11001095        if ch not in u'\0 \r\n\x85\u2028\u2029': 
    11011096            raise ScannerError("while scanning a block scalar", start_mark, 
    11021097                    "expected chomping or indentation indicators, but found %r" 
    1103                         % ch.encode('utf-8'), self.reader.get_mark()) 
     1098                        % ch.encode('utf-8'), self.get_mark()) 
    11041099        return chomping, increment 
    11051100 
    11061101    def scan_block_scalar_ignored_line(self, start_mark): 
    11071102        # See the specification for details. 
    1108         while self.reader.peek() == u' ': 
    1109             self.reader.forward() 
    1110         if self.reader.peek() == u'#': 
    1111             while self.reader.peek() not in u'\0\r\n\x85\u2028\u2029': 
    1112                 self.reader.forward() 
    1113         ch = self.reader.peek() 
     1103        while self.peek() == u' ': 
     1104            self.forward() 
     1105        if self.peek() == u'#': 
     1106            while self.peek() not in u'\0\r\n\x85\u2028\u2029': 
     1107                self.forward() 
     1108        ch = self.peek() 
    11141109        if ch not in u'\0\r\n\x85\u2028\u2029': 
    11151110            raise ScannerError("while scanning a block scalar", start_mark, 
    11161111                    "expected a comment or a line break, but found %r" 
    1117                         % ch.encode('utf-8'), self.reader.get_mark()) 
     1112                        % ch.encode('utf-8'), self.get_mark()) 
    11181113        self.scan_line_break() 
    11191114 
     
    11221117        chunks = [] 
    11231118        max_indent = 0 
    1124         end_mark = self.reader.get_mark() 
    1125         while self.reader.peek() in u' \r\n\x85\u2028\u2029': 
    1126             if self.reader.peek() != u' ': 
     1119        end_mark = self.get_mark() 
     1120        while self.peek() in u' \r\n\x85\u2028\u2029': 
     1121            if self.peek() != u' ': 
    11271122                chunks.append(self.scan_line_break()) 
    1128                 end_mark = self.reader.get_mark() 
     1123                end_mark = self.get_mark() 
    11291124            else: 
    1130                 self.reader.forward() 
    1131                 if self.reader.column > max_indent: 
    1132                     max_indent = self.reader.column 
     1125                self.forward() 
     1126                if self.column > max_indent: 
     1127                    max_indent = self.column 
    11331128        return chunks, max_indent, end_mark 
    11341129 
     
    11361131        # See the specification for details. 
    11371132        chunks = [] 
    1138         end_mark = self.reader.get_mark() 
    1139         while self.reader.column < indent and self.reader.peek() == u' ': 
    1140             self.reader.forward() 
    1141         while self.reader.peek() in u'\r\n\x85\u2028\u2029': 
     1133        end_mark = self.get_mark() 
     1134        while self.column < indent and self.peek() == u' ': 
     1135            self.forward() 
     1136        while self.peek() in u'\r\n\x85\u2028\u2029': 
    11421137            chunks.append(self.scan_line_break()) 
    1143             end_mark = self.reader.get_mark() 
    1144             while self.reader.column < indent and self.reader.peek() == u' ': 
    1145                 self.reader.forward() 
     1138            end_mark = self.get_mark() 
     1139            while self.column < indent and self.peek() == u' ': 
     1140                self.forward() 
    11461141        return chunks, end_mark 
    11471142 
     
    11581153            double = False 
    11591154        chunks = [] 
    1160         start_mark = self.reader.get_mark() 
    1161         quote = self.reader.peek() 
    1162         self.reader.forward() 
     1155        start_mark = self.get_mark() 
     1156        quote = self.peek() 
     1157        self.forward() 
    11631158        chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) 
    1164         while self.reader.peek() != quote: 
     1159        while self.peek() != quote: 
    11651160            chunks.extend(self.scan_flow_scalar_spaces(double, start_mark)) 
    11661161            chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) 
    1167         self.reader.forward() 
    1168         end_mark = self.reader.get_mark() 
     1162        self.forward() 
     1163        end_mark = self.get_mark() 
    11691164        return ScalarToken(u''.join(chunks), False, start_mark, end_mark, 
    11701165                style) 
     
    12011196        while True: 
    12021197            length = 0 
    1203             while self.reader.peek(length) not in u'\'\"\\\0 \t\r\n\x85\u2028\u2029': 
     1198            while self.peek(length) not in u'\'\"\\\0 \t\r\n\x85\u2028\u2029': 
    12041199                length += 1 
    12051200            if length: 
    1206                 chunks.append(self.reader.prefix(length)) 
    1207                 self.reader.forward(length) 
    1208             ch = self.reader.peek() 
    1209             if not double and ch == u'\'' and self.reader.peek(1) == u'\'': 
     1201                chunks.append(self.prefix(length)) 
     1202                self.forward(length) 
     1203            ch = self.peek() 
     1204            if not double and ch == u'\'' and self.peek(1) == u'\'': 
    12101205                chunks.append(u'\'') 
    1211                 self.reader.forward(2) 
     1206                self.forward(2) 
    12121207            elif (double and ch == u'\'') or (not double and ch in u'\"\\'): 
    12131208                chunks.append(ch) 
    1214                 self.reader.forward() 
     1209                self.forward() 
    12151210            elif double and ch == u'\\': 
    1216                 self.reader.forward() 
    1217                 ch = self.reader.peek() 
     1211                self.forward() 
     1212                ch = self.peek() 
    12181213                if ch in self.ESCAPE_REPLACEMENTS: 
    12191214                    chunks.append(self.ESCAPE_REPLACEMENTS[ch]) 
    1220                     self.reader.forward() 
     1215                    self.forward() 
    12211216                elif ch in self.ESCAPE_CODES: 
    12221217                    length = self.ESCAPE_CODES[ch] 
    1223                     self.reader.forward() 
     1218                    self.forward() 
    12241219                    for k in range(length): 
    1225                         if self.reader.peek(k) not in u'0123456789ABCDEFabcdef': 
     1220                        if self.peek(k) not in u'0123456789ABCDEFabcdef': 
    12261221                            raise ScannerError("while scanning a double-quoted scalar", start_mark, 
    12271222                                    "expected escape sequence of %d hexdecimal numbers, but found %r" % 
    1228                                         (length, self.reader.peek(k).encode('utf-8')), self.reader.get_mark()) 
    1229                     code = int(self.reader.prefix(length), 16) 
     1223                                        (length, self.peek(k).encode('utf-8')), self.get_mark()) 
     1224                    code = int(self.prefix(length), 16) 
    12301225                    chunks.append(unichr(code)) 
    1231                     self.reader.forward(length) 
     1226                    self.forward(length) 
    12321227                elif ch in u'\r\n\x85\u2028\u2029': 
    12331228                    self.scan_line_break() 
     
    12351230                else: 
    12361231                    raise ScannerError("while scanning a double-quoted scalar", start_mark, 
    1237                             "found unknown escape character %r" % ch.encode('utf-8'), self.reader.get_mark()) 
     1232                            "found unknown escape character %r" % ch.encode('utf-8'), self.get_mark()) 
    12381233            else: 
    12391234                return chunks 
     
    12431238        chunks = [] 
    12441239        length = 0 
    1245         while self.reader.peek(length) in u' \t': 
     1240        while self.peek(length) in u' \t': 
    12461241            length += 1 
    1247         whitespaces = self.reader.prefix(length) 
    1248         self.reader.forward(length) 
    1249         ch = self.reader.peek() 
     1242        whitespaces = self.prefix(length) 
     1243        self.forward(length) 
     1244        ch = self.peek() 
    12501245        if ch == u'\0': 
    12511246            raise ScannerError("while scanning a quoted scalar", start_mark, 
    1252                     "found unexpected end of stream", self.reader.get_mark()) 
     1247                    "found unexpected end of stream", self.get_mark()) 
    12531248        elif ch in u'\r\n\x85\u2028\u2029': 
    12541249            line_break = self.scan_line_break() 
     
    12691264            # Instead of checking indentation, we check for document 
    12701265            # separators. 
    1271             prefix = self.reader.prefix(3) 
     1266            prefix = self.prefix(3) 
    12721267            if (prefix == u'---' or prefix == u'...')   \ 
    1273                     and self.reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
     1268                    and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
    12741269                raise ScannerError("while scanning a quoted scalar", start_mark, 
    1275                         "found unexpected document separator", self.reader.get_mark()) 
    1276             while self.reader.peek() in u' \t': 
    1277                 self.reader.forward() 
    1278             if self.reader.peek() in u'\r\n\x85\u2028\u2029': 
     1270                        "found unexpected document separator", self.get_mark()) 
     1271            while self.peek() in u' \t': 
     1272                self.forward() 
     1273            if self.peek() in u'\r\n\x85\u2028\u2029': 
    12791274                chunks.append(self.scan_line_break()) 
    12801275            else: 
     
    12881283        # Indentation rules are loosed for the flow context. 
    12891284        chunks = [] 
    1290         start_mark = self.reader.get_mark() 
     1285        start_mark = self.get_mark() 
    12911286        end_mark = start_mark 
    12921287        indent = self.indent+1 
     
    12981293        while True: 
    12991294            length = 0 
    1300             if self.reader.peek() == u'#': 
     1295            if self.peek() == u'#': 
    13011296                break 
    13021297            while True: 
    1303                 ch = self.reader.peek(length) 
     1298                ch = self.peek(length) 
    13041299                if ch in u'\0 \t\r\n\x85\u2028\u2029'   \ 
    13051300                        or (not self.flow_level and ch == u':' and 
    1306                                 self.reader.peek(length+1) in u'\0 \t\r\n\x28\u2028\u2029') \ 
     1301                                self.peek(length+1) in u'\0 \t\r\n\x28\u2028\u2029') \ 
    13071302                        or (self.flow_level and ch in u',:?[]{}'): 
    13081303                    break 
     
    13121307            self.allow_simple_key = False 
    13131308            chunks.extend(spaces) 
    1314             chunks.append(self.reader.prefix(length)) 
    1315             self.reader.forward(length) 
    1316             end_mark = self.reader.get_mark() 
     1309            chunks.append(self.prefix(length)) 
     1310            self.forward(length) 
     1311            end_mark = self.get_mark() 
    13171312            spaces = self.scan_plain_spaces(indent, start_mark) 
    1318             if not spaces or self.reader.peek() == u'#' \ 
    1319                     or (not self.flow_level and self.reader.column < indent): 
     1313            if not spaces or self.peek() == u'#' \ 
     1314                    or (not self.flow_level and self.column < indent): 
    13201315                break 
    13211316        return ScalarToken(u''.join(chunks), True, start_mark, end_mark) 
     
    13271322        chunks = [] 
    13281323        length = 0 
    1329         while self.reader.peek(length) in u' ': 
     1324        while self.peek(length) in u' ': 
    13301325            length += 1 
    1331         whitespaces = self.reader.prefix(length) 
    1332         self.reader.forward(length) 
    1333         ch = self.reader.peek() 
     1326        whitespaces = self.prefix(length) 
     1327        self.forward(length) 
     1328        ch = self.peek() 
    13341329        if ch in u'\r\n\x85\u2028\u2029': 
    13351330            line_break = self.scan_line_break() 
    13361331            self.allow_simple_key = True 
    1337             prefix = self.reader.prefix(3) 
     1332            prefix = self.prefix(3) 
    13381333            if (prefix == u'---' or prefix == u'...')   \ 
    1339                     and self.reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
     1334                    and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
    13401335                return 
    13411336            breaks = [] 
    1342             while self.reader.peek() in u' \r\n\x85\u2028\u2029': 
    1343                 if self.reader.peek() == ' ': 
    1344                     self.reader.forward() 
     1337            while self.peek() in u' \r\n\x85\u2028\u2029': 
     1338                if self.peek() == ' ': 
     1339                    self.forward() 
    13451340                else: 
    13461341                    breaks.append(self.scan_line_break()) 
    1347                     prefix = self.reader.prefix(3) 
     1342                    prefix = self.prefix(3) 
    13481343                    if (prefix == u'---' or prefix == u'...')   \ 
    1349                             and self.reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
     1344                            and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 
    13501345                        return 
    13511346            if line_break != u'\n': 
     
    13621357        # For some strange reasons, the specification does not allow '_' in 
    13631358        # tag handles. I have allowed it anyway. 
    1364         ch = self.reader.peek() 
     1359        ch = self.peek() 
    13651360        if ch != u'!': 
    13661361            raise ScannerError("while scanning a %s" % name, start_mark, 
    13671362                    "expected '!', but found %r" % ch.encode('utf-8'), 
    1368                     self.reader.get_mark()) 
     1363                    self.get_mark()) 
    13691364        length = 1 
    1370         ch = self.reader.peek(length) 
     1365        ch = self.peek(length) 
    13711366        if ch != u' ': 
    13721367            while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z'  \ 
    13731368                    or ch in u'-_': 
    13741369                length += 1 
    1375                 ch = self.reader.peek(length) 
     1370                ch = self.peek(length) 
    13761371            if ch != u'!': 
    1377                 self.reader.forward(length) 
     1372                self.forward(length) 
    13781373                raise ScannerError("while scanning a %s" % name, start_mark, 
    13791374                        "expected '!', but found %r" % ch.encode('utf-8'), 
    1380                         self.reader.get_mark()) 
     1375                        self.get_mark()) 
    13811376            length += 1 
    1382         value = self.reader.prefix(length) 
    1383         self.reader.forward(length) 
     1377        value = self.prefix(length) 
     1378        self.forward(length) 
    13841379        return value 
    13851380 
     
    13891384        chunks = [] 
    13901385        length = 0 
    1391         ch = self.reader.peek(length) 
     1386        ch = self.peek(length) 
    13921387        while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z'  \ 
    13931388                or ch in u'-;/?:@&=+$,_.!~*\'()[]%': 
    13941389            if ch == u'%': 
    1395                 chunks.append(self.reader.prefix(length)) 
    1396                 self.reader.forward(length) 
     1390                chunks.append(self.prefix(length)) 
     1391                self.forward(length) 
    13971392                length = 0 
    13981393                chunks.append(self.scan_uri_escapes(name, start_mark)) 
    13991394            else: 
    14001395                length += 1 
    1401             ch = self.reader.peek(length) 
     1396            ch = self.peek(length) 
    14021397        if length: 
    1403             chunks.append(self.reader.prefix(length)) 
    1404             self.reader.forward(length) 
     1398            chunks.append(self.prefix(length)) 
     1399            self.forward(length) 
    14051400            length = 0 
    14061401        if not chunks: 
    14071402            raise ScannerError("while parsing a %s" % name, start_mark, 
    14081403                    "expected URI, but found %r" % ch.encode('utf-8'), 
    1409                     self.reader.get_mark()) 
     1404                    self.get_mark()) 
    14101405        return u''.join(chunks) 
    14111406 
     
    14131408        # See the specification for details. 
    14141409        bytes = [] 
    1415         mark = self.reader.get_mark() 
    1416         while self.reader.peek() == u'%': 
    1417             self.reader.forward() 
     1410        mark = self.get_mark() 
     1411        while self.peek() == u'%': 
     1412            self.forward() 
    14181413            for k in range(2): 
    1419                 if self.reader.peek(k) not in u'0123456789ABCDEFabcdef': 
     1414                if self.peek(k) not in u'0123456789ABCDEFabcdef': 
    14201415                    raise ScannerError("while scanning a %s" % name, start_mark, 
    14211416                            "expected URI escape sequence of 2 hexdecimal numbers, but found %r" % 
    1422                                 (self.reader.peek(k).encode('utf-8')), self.reader.get_mark()) 
    1423             bytes.append(chr(int(self.reader.prefix(2), 16))) 
    1424             self.reader.forward(2) 
     1417                                (self.peek(k).encode('utf-8')), self.get_mark()) 
     1418            bytes.append(chr(int(self.prefix(2), 16))) 
     1419            self.forward(2) 
    14251420        try: 
    14261421            value = unicode(''.join(bytes), 'utf-8') 
     
    14381433        #   '\u2029     :   '\u2029' 
    14391434        #   default     :   '' 
    1440         ch = self.reader.peek() 
     1435        ch = self.peek() 
    14411436        if ch in u'\r\n\x85': 
    1442             if self.reader.prefix(2) == u'\r\n': 
    1443                 self.reader.forward(2) 
     1437            if self.prefix(2) == u'\r\n': 
     1438                self.forward(2) 
    14441439            else: 
    1445                 self.reader.forward() 
     1440                self.forward() 
    14461441            return u'\n' 
    14471442        elif ch in u'\u2028\u2029': 
    1448             self.reader.forward() 
     1443            self.forward() 
    14491444            return ch 
    14501445        return u'' 
  • pyyaml/trunk/lib/yaml/serializer.py

    r135 r136  
    1313    ANCHOR_TEMPLATE = u'id%03d' 
    1414 
    15     def __init__(self, emitter, encoding=None, line_break=None, canonical=None, 
    16             indent=None, width=None, allow_unicode=None): 
    17         self.emitter = emitter 
     15    def __init__(self, encoding=None, 
     16            explicit_start=None, explicit_end=None, version=None, tags=None): 
     17        self.use_encoding = encoding 
     18        self.use_explicit_start = explicit_start 
     19        self.use_explicit_end = explicit_end 
     20        self.use_version = version 
     21        self.use_tags = tags 
    1822        self.serialized_nodes = {} 
    1923        self.anchors = {} 
    2024        self.last_anchor_id = 0 
    2125        self.closed = None 
    22         self.open(encoding, line_break, canonical, indent, width, allow_unicode) 
    2326 
    24     def open(self, encoding=None, line_break=None, canonical=None, 
    25             indent=None, width=None, allow_unicode=None): 
     27    def open(self): 
    2628        if self.closed is None: 
    27             self.emitter.emit(StreamStartEvent(encoding=encoding, 
    28                 line_break=line_break, canonical=canonical, 
    29                 indent=indent, width=width, allow_unicode=allow_unicode)) 
     29            self.emit(StreamStartEvent(encoding=self.use_encoding)) 
    3030            self.closed = False 
    3131        elif self.closed: 
     
    3838            raise SerializerError("serializer is not opened") 
    3939        elif not self.closed: 
    40             self.emitter.emit(StreamEndEvent()) 
     40            self.emit(StreamEndEvent()) 
    4141            self.closed = True 
    4242 
    43     def __del__(self): 
    44         self.close() 
     43    #def __del__(self): 
     44    #    self.close() 
    4545 
    46     def serialize(self, node, explicit_start=None, explicit_end=None, 
    47             version=None, tags=None): 
     46    def serialize(self, node): 
    4847        if self.closed is None: 
    4948            raise SerializerError("serializer is not opened") 
    5049        elif self.closed: 
    5150            raise SerializerError("serializer is closed") 
    52         self.emitter.emit(DocumentStartEvent(explicit=explicit_start, 
    53             version=version, tags=tags)) 
     51        self.emit(DocumentStartEvent(explicit=self.use_explicit_start, 
     52            version=self.use_version, tags=self.use_tags)) 
    5453        self.anchor_node(node) 
    5554        self.serialize_node(node) 
    56         self.emitter.emit(DocumentEndEvent(explicit=explicit_end)) 
     55        self.emit(DocumentEndEvent(explicit=self.use_explicit_end)) 
    5756        self.serialized_nodes = {} 
    5857        self.anchors = {} 
     
    8079        alias = self.anchors[node] 
    8180        if node in self.serialized_nodes: 
    82             self.emitter.emit(AliasEvent(alias)) 
     81            self.emit(AliasEvent(alias)) 
    8382        else: 
    8483            self.serialized_nodes[node] = True 
    8584            if isinstance(node, ScalarNode): 
    86                 self.emitter.emit(ScalarEvent(alias, node.tag, node.value, 
    87                     implicit=node.implicit, style=node.style)) 
     85                detected_tag = self.detect(node.value) 
     86                implicit = (node.tag == self.detect(node.value) 
     87                        or (node.tag == self.DEFAULT_SCALAR_TAG 
     88                            and detected_tag is None)) 
     89                self.emit(ScalarEvent(alias, node.tag, implicit, node.value, 
     90                    style=node.style)) 
    8891            elif isinstance(node, SequenceNode): 
    89                 self.emitter.emit(SequenceStartEvent(alias, node.tag, 
     92                # TODO: 
     93                # 1) Check the current path in the Resolver. 
     94                # 2) Add the implicit flag to the SequenceStartEvent and 
     95                # MappingStartEvent. 
     96                tag = node.tag 
     97                if tag == self.DEFAULT_SEQUENCE_TAG and not self.canonical: 
     98                    tag = None 
     99                self.emit(SequenceStartEvent(alias, tag, 
    90100                    flow_style=node.flow_style)) 
    91101                for item in node.value: 
    92102                    self.serialize_node(item) 
    93                 self.emitter.emit(SequenceEndEvent()) 
     103                self.emit(SequenceEndEvent()) 
    94104            elif isinstance(node, MappingNode): 
    95                 self.emitter.emit(MappingStartEvent(alias, node.tag, 
     105                tag = node.tag 
     106                if tag == self.DEFAULT_MAPPING_TAG and not self.canonical: 
     107                    tag = None 
     108                self.emit(MappingStartEvent(alias, tag, 
    96109                    flow_style=node.flow_style)) 
    97                 for key in node.value: 
    98                     self.serialize_node(key) 
    99                     self.serialize_node(node.value[key]) 
    100                 self.emitter.emit(MappingEndEvent()) 
     110                if hasattr(node.value, 'keys'): 
     111                    for key in node.value.keys(): 
     112                        self.serialize_node(key) 
     113                        self.serialize_node(node.value[key]) 
     114                else: 
     115                    for key, value in node.value: 
     116                        self.serialize_node(key) 
     117                        self.serialize_node(value) 
     118                self.emit(MappingEndEvent()) 
    101119 
  • pyyaml/trunk/tests/data/construct-custom.code

    r58 r136  
    77    MyTestClass3(x=1, y=2, z=3), 
    88    MyTestClass3(x=1, y=2, z=3), 
     9    YAMLObject1(my_parameter='foo', my_another_parameter=[1,2,3]) 
    910] 
  • pyyaml/trunk/tests/data/construct-custom.data

    r58 r136  
    2222  'y': 2 
    2323  z: 3 
     24- !foo 
     25  my-parameter: foo 
     26  my-another-parameter: [1,2,3] 
  • pyyaml/trunk/tests/data/spec-08-07.canonical

    r38 r136  
    44  !<tag:yaml.org,2002:str> "12", 
    55  !<tag:yaml.org,2002:int> "12", 
    6   !<tag:yaml.org,2002:str> "12", 
     6#  !<tag:yaml.org,2002:str> "12", 
     7  !<tag:yaml.org,2002:int> "12", 
    78] 
  • pyyaml/trunk/tests/data/tags.events

    r132 r136  
    33- !SequenceStart 
    44- !Scalar { value: 'data' } 
    5 - !Scalar { tag: '!', value: 'data' } 
     5#- !Scalar { tag: '!', value: 'data' } 
    66- !Scalar { tag: 'tag:yaml.org,2002:str', value: 'data' } 
    77- !Scalar { tag: '!myfunnytag', value: 'data' } 
  • pyyaml/trunk/tests/test_appliance.py

    r132 r136  
    22import unittest, os 
    33 
    4 from yaml.tokens import * 
    5 from yaml.events import * 
     4from yaml import * 
    65 
    76class TestAppliance(unittest.TestCase): 
     
    4443        self.data = unicode(data, 'utf-8')+u'\0' 
    4544        self.index = 0 
     45        self.scan() 
     46 
     47    def check_token(self, *choices): 
     48        if self.tokens: 
     49            if not choices: 
     50                return True 
     51            for choice in choices: 
     52                if isinstance(self.tokens[0], choice): 
     53                    return True 
     54        return False 
     55 
     56    def peek_token(self): 
     57        if self.tokens: 
     58            return self.tokens[0] 
     59 
     60    def get_token(self, choice=None): 
     61        token = self.tokens.pop(0) 
     62        if choice and not isinstance(token, choice): 
     63            raise Error("unexpected token "+repr(token)) 
     64        return token 
     65 
     66    def get_token_value(self): 
     67        token = self.get_token() 
     68        return token.value 
    4669 
    4770    def scan(self): 
    48         #print self.data[self.index:] 
    49         tokens = [] 
    50         tokens.append(StreamStartToken(None, None)) 
     71        self.tokens = [] 
     72        self.tokens.append(StreamStartToken(None, None)) 
    5173        while True: 
    5274            self.find_token() 
    5375            ch = self.data[self.index] 
    5476            if ch == u'\0': 
    55                 tokens.append(StreamEndToken(None, None)) 
     77                self.tokens.append(StreamEndToken(None, None)) 
    5678                break 
    5779            elif ch == u'%': 
    58                 tokens.append(self.scan_directive()) 
     80                self.tokens.append(self.scan_directive()) 
    5981            elif ch == u'-' and self.data[self.index:self.index+3] == u'---': 
    6082                self.index += 3 
    61                 tokens.append(DocumentStartToken(None, None)) 
     83                self.tokens.append(DocumentStartToken(None, None)) 
    6284            elif ch == u'[': 
    6385                self.index += 1 
    64                 tokens.append(FlowSequenceStartToken(None, None)) 
     86                self.tokens.append(FlowSequenceStartToken(None, None)) 
    6587            elif ch == u'{': 
    6688                self.index += 1 
    67                 tokens.append(FlowMappingStartToken(None, None)) 
     89                self.tokens.append(FlowMappingStartToken(None, None)) 
    6890            elif ch == u']': 
    6991                self.index += 1 
    70                 tokens.append(FlowSequenceEndToken(None, None)) 
     92                self.tokens.append(FlowSequenceEndToken(None, None)) 
    7193            elif ch == u'}': 
    7294                self.index += 1 
    73                 tokens.append(FlowMappingEndToken(None, None)) 
     95                self.tokens.append(FlowMappingEndToken(None, None)) 
    7496            elif ch == u'?': 
    7597                self.index += 1 
    76                 tokens.append(KeyToken(None, None)) 
     98                self.tokens.append(KeyToken(None, None)) 
    7799            elif ch == u':': 
    78100                self.index += 1 
    79                 tokens.append(ValueToken(None, None)) 
     101                self.tokens.append(ValueToken(None, None)) 
    80102            elif ch == u',': 
    81103                self.index += 1 
    82                 tokens.append(FlowEntryToken(None, None)) 
     104                self.tokens.append(FlowEntryToken(None, None)) 
    83105            elif ch == u'*' or ch == u'&': 
    84                 tokens.append(self.scan_alias()) 
     106                self.tokens.append(self.scan_alias()) 
    85107            elif ch == u'!': 
    86                 tokens.append(self.scan_tag()) 
     108                self.tokens.append(self.scan_tag()) 
    87109            elif ch == u'"': 
    88                 tokens.append(self.scan_scalar()) 
     110                self.tokens.append(self.scan_scalar()) 
    89111            else: 
    90112                raise Error("invalid token") 
    91         return tokens 
    92113 
    93114    DIRECTIVE = u'%YAML 1.1' 
     
    204225class CanonicalParser: 
    205226 
    206     def __init__(self, data): 
    207         self.scanner = CanonicalScanner(data) 
     227    def __init__(self): 
    208228        self.events = [] 
     229        self.parse() 
    209230 
    210231    # stream: STREAM-START document* STREAM-END 
    211232    def parse_stream(self): 
    212         self.consume_token(StreamStartToken) 
     233        self.get_token(StreamStartToken) 
    213234        self.events.append(StreamStartEvent(None, None)) 
    214         while not self.test_token(StreamEndToken): 
    215             if self.test_token(DirectiveToken, DocumentStartToken): 
     235        while not self.check_token(StreamEndToken): 
     236            if self.check_token(DirectiveToken, DocumentStartToken): 
    216237                self.parse_document() 
    217238            else: 
    218239                raise Error("document is expected, got "+repr(self.tokens[self.index])) 
    219         self.consume_token(StreamEndToken) 
     240        self.get_token(StreamEndToken) 
    220241        self.events.append(StreamEndEvent(None, None)) 
    221242 
     
    223244    def parse_document(self): 
    224245        node = None 
    225         if self.test_token(DirectiveToken): 
    226             self.consume_token(DirectiveToken) 
    227         self.consume_token(DocumentStartToken) 
     246        if self.check_token(DirectiveToken): 
     247            self.get_token(DirectiveToken) 
     248        self.get_token(DocumentStartToken) 
    228249        self.events.append(DocumentStartEvent(None, None)) 
    229250        self.parse_node() 
     
    232253    # node: ALIAS | ANCHOR? TAG? (SCALAR|sequence|mapping) 
    233254    def parse_node(self): 
    234         if self.test_token(AliasToken): 
    235             self.events.append(AliasEvent(self.get_value(), None, None)) 
     255        if self.check_token(AliasToken): 
     256            self.events.append(AliasEvent(self.get_token_value(), None, None)) 
    236257        else: 
    237258            anchor = None 
    238             if self.test_token(AnchorToken): 
    239                 anchor = self.get_value() 
     259            if self.check_token(AnchorToken): 
     260                anchor = self.get_token_value() 
    240261            tag = None 
    241             if self.test_token(TagToken): 
    242                 tag = self.get_value() 
    243             if self.test_token(ScalarToken): 
    244                 self.events.append(ScalarEvent(anchor, tag, self.get_value(), None, None)) 
    245             elif self.test_token(FlowSequenceStartToken): 
     262            if self.check_token(TagToken): 
     263                tag = self.get_token_value() 
     264            if self.check_token(ScalarToken): 
     265                self.events.append(ScalarEvent(anchor, tag, False, self.get_token_value(), None, None)) 
     266            elif self.check_token(FlowSequenceStartToken): 
    246267                self.events.append(SequenceStartEvent(anchor, tag, None, None)) 
    247268                self.parse_sequence() 
    248             elif self.test_token(FlowMappingStartToken): 
     269            elif self.check_token(FlowMappingStartToken): 
    249270                self.events.append(MappingStartEvent(anchor, tag, None, None)) 
    250271                self.parse_mapping() 
     
    254275    # sequence: SEQUENCE-START (node (ENTRY node)*)? ENTRY? SEQUENCE-END 
    255276    def parse_sequence(self): 
    256         self.consume_token(FlowSequenceStartToken) 
    257         if not self.test_token(FlowSequenceEndToken): 
     277        self.get_token(FlowSequenceStartToken) 
     278        if not self.check_token(FlowSequenceEndToken): 
    258279            self.parse_node() 
    259             while not self.test_token(FlowSequenceEndToken): 
    260                 self.consume_token(FlowEntryToken) 
    261                 if not self.test_token(FlowSequenceEndToken): 
     280            while not self.check_token(FlowSequenceEndToken): 
     281                self.get_token(FlowEntryToken) 
     282                if not self.check_token(FlowSequenceEndToken): 
    262283                    self.parse_node() 
    263         self.consume_token(FlowSequenceEndToken) 
     284        self.get_token(FlowSequenceEndToken) 
    264285        self.events.append(SequenceEndEvent(None, None)) 
    265286 
    266287    # mapping: MAPPING-START (map_entry (ENTRY map_entry)*)? ENTRY? MAPPING-END 
    267288    def parse_mapping(self): 
    268         self.consume_token(FlowMappingStartToken) 
    269         if not self.test_token(FlowMappingEndToken): 
     289        self.get_token(FlowMappingStartToken) 
     290        if not self.check_token(FlowMappingEndToken): 
    270291            self.parse_map_entry() 
    271             while not self.test_token(FlowMappingEndToken): 
    272                 self.consume_token(FlowEntryToken) 
    273                 if not self.test_token(FlowMappingEndToken): 
     292            while not self.check_token(FlowMappingEndToken): 
     293                self.get_token(FlowEntryToken) 
     294                if not self.check_token(FlowMappingEndToken): 
    274295                    self.parse_map_entry() 
    275         self.consume_token(FlowMappingEndToken) 
     296        self.get_token(FlowMappingEndToken) 
    276297        self.events.append(MappingEndEvent(None, None)) 
    277298 
    278299    # map_entry: KEY node VALUE node 
    279300    def parse_map_entry(self): 
    280         self.consume_token(KeyToken) 
     301        self.get_token(KeyToken) 
    281302        self.parse_node() 
    282         self.consume_token(ValueToken) 
     303        self.get_token(ValueToken) 
    283304        self.parse_node() 
    284305 
    285     def test_token(self, *choices): 
    286         for choice in choices: 
    287             if isinstance(self.tokens[self.index], choice): 
     306    def parse(self): 
     307        self.parse_stream() 
     308 
     309    def get_event(self): 
     310        return self.events.pop(0) 
     311 
     312    def check_event(self, *choices): 
     313        if self.events: 
     314            if not choices: 
    288315                return True 
     316            for choice in choices: 
     317                if isinstance(self.events[0], choice): 
     318                    return True 
    289319        return False 
    290320 
    291     def consume_token(self, cls): 
    292         if not isinstance(self.tokens[self.index], cls): 
    293             raise Error("unexpected token "+repr(self.tokens[self.index])) 
    294         self.index += 1 
    295  
    296     def get_value(self): 
    297         value = self.tokens[self.index].value 
    298         self.index += 1 
    299         return value 
    300  
    301     def parse(self): 
    302         self.tokens = self.scanner.scan() 
    303         self.index = 0 
    304         self.parse_stream() 
    305         return self.events 
    306  
    307     def get(self): 
    308         return self.events.pop(0) 
    309  
    310     def check(self, *choices): 
    311         for choice in choices: 
    312             if isinstance(self.events[0], choice): 
    313                 return True 
    314         return False 
    315  
    316     def peek(self): 
     321    def peek_event(self): 
    317322        return self.events[0] 
    318323 
     324class CanonicalLoader(CanonicalScanner, CanonicalParser, Composer, Constructor, Detector): 
     325 
     326    def __init__(self, stream): 
     327        if hasattr(stream, 'read'): 
     328            stream = stream.read() 
     329        CanonicalScanner.__init__(self, stream) 
     330        CanonicalParser.__init__(self) 
     331        Composer.__init__(self) 
     332        Constructor.__init__(self) 
     333        Detector.__init__(self) 
     334 
     335def canonical_scan(stream): 
     336    return scan(stream, Loader=CanonicalLoader) 
     337 
     338def canonical_parse(stream): 
     339    return parse(stream, Loader=CanonicalLoader) 
     340 
     341def canonical_compose(stream): 
     342    return compose(stream, Loader=CanonicalLoader) 
     343 
     344def canonical_compose_all(stream): 
     345    return compose_all(stream, Loader=CanonicalLoader) 
     346 
     347def canonical_load(stream): 
     348    return load(stream, Loader=CanonicalLoader) 
     349 
     350def canonical_load_all(stream): 
     351    return load_all(stream, Loader=CanonicalLoader) 
     352 
  • pyyaml/trunk/tests/test_canonical.py

    r51 r136  
    66    def _testCanonicalScanner(self, test_name, canonical_filename): 
    77        data = file(canonical_filename, 'rb').read() 
    8         scanner = test_appliance.CanonicalScanner(data) 
    9         tokens = scanner.scan() 
     8        tokens = list(test_appliance.canonical_scan(data)) 
    109        #for token in tokens: 
    1110        #    print token 
     
    1312    def _testCanonicalParser(self, test_name, canonical_filename): 
    1413        data = file(canonical_filename, 'rb').read() 
    15         parser = test_appliance.CanonicalParser(data) 
    16         events = parser.parse() 
     14        event = list(test_appliance.canonical_parse(data)) 
    1715        #for event in events: 
    1816        #    print event 
  • pyyaml/trunk/tests/test_constructor.py

    r59 r136  
    1212from yaml import * 
    1313 
    14 class MyConstructor(Constructor): 
     14class MyLoader(Loader): 
    1515    pass 
    1616 
     
    2929    return MyTestClass1(**mapping) 
    3030 
    31 MyConstructor.add_constructor("!tag1", construct1) 
     31MyLoader.add_constructor("!tag1", construct1) 
    3232 
    3333class MyTestClass2(MyTestClass1, YAMLObject): 
    3434 
    35     yaml_constructor = MyConstructor 
     35    yaml_loader = MyLoader 
    3636    yaml_tag = "!tag2" 
    3737 
     
    5454    from_yaml = classmethod(from_yaml) 
    5555 
     56class YAMLObject1(YAMLObject): 
     57    yaml_loader = MyLoader 
     58    yaml_tag = '!foo' 
     59 
     60    def __init__(self, my_parameter=None, my_another_parameter=None): 
     61        self.my_parameter = my_parameter 
     62        self.my_another_parameter = my_another_parameter 
     63 
     64    def __eq__(self, other): 
     65        if isinstance(other, YAMLObject1): 
     66            return self.__class__, self.__dict__ == other.__class__, other.__dict__ 
     67        else: 
     68            return False 
     69 
    5670class TestTypes(test_appliance.TestAppliance): 
    5771 
    5872    def _testTypes(self, test_name, data_filename, code_filename): 
    59         natives1 = None 
    60         natives2 = None 
     73        data1 = None 
     74        data2 = None 
    6175        try: 
    62             constructor1 = MyConstructor(Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb'))))))) 
    63             natives1 = list(iter(constructor1)) 
    64             if len(natives1) == 1: 
    65                 natives1 = natives1[0] 
    66             natives2 = eval(file(code_filename, 'rb').read()) 
     76            data1 = list(load_all(file(data_filename, 'rb'), Loader=MyLoader)) 
     77            if len(data1) == 1: 
     78                data1 = data1[0] 
     79            data2 = eval(file(code_filename, 'rb').read()) 
    6780            try: 
    68                 self.failUnlessEqual(natives1, natives2) 
     81                self.failUnlessEqual(data1, data2) 
    6982            except AssertionError: 
    70                 if isinstance(natives1, dict): 
    71                     natives1 = natives1.items() 
    72                     natives1.sort() 
    73                     natives1 = repr(natives1) 
    74                     natives2 = natives2.items() 
    75                     natives2.sort() 
    76                     natives2 = repr(natives2) 
    77                 if natives1 != natives2: 
     83                if isinstance(data1, dict): 
     84                    data1 = data1.items() 
     85                    data1.sort() 
     86                    data1 = repr(data1) 
     87                    data2 = data2.items() 
     88                    data2.sort() 
     89                    data2 = repr(data2) 
     90                if data1 != data2: 
    7891                    raise 
    7992        except: 
     
    8396            print "CODE:" 
    8497            print file(code_filename, 'rb').read() 
    85             print "NATIVES1:", natives1 
    86             print "NATIVES2:", natives2 
     98            print "NATIVES1:", data1 
     99            print "NATIVES2:", data2 
    87100            raise 
    88101 
  • pyyaml/trunk/tests/test_detector.py

    r55 r136  
    22import test_appliance 
    33 
    4 from yaml.reader import Reader 
    5 from yaml.scanner import Scanner 
    6 from yaml.parser import * 
    7 from yaml.composer import * 
    8 from yaml.resolver import * 
    9 from yaml.nodes import * 
     4from yaml import * 
    105 
    116class TestDetector(test_appliance.TestAppliance): 
     
    1611        try: 
    1712            correct_tag = file(detect_filename, 'rb').read().strip() 
    18             resolver = Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb')))))) 
    19             node = list(iter(resolver))[0] 
     13            node = compose(file(data_filename, 'rb')) 
    2014            self.failUnless(isinstance(node, SequenceNode)) 
    2115            for scalar in node.value: 
     
    3428TestDetector.add_tests('testDetector', '.data', '.detect') 
    3529 
    36  
  • pyyaml/trunk/tests/test_emitter.py

    r133 r136  
    1717 
    1818    def _testEmitter(self, test_name, filename, canonical=None): 
    19         events = list(iter(Parser(Scanner(Reader(file(filename, 'rb')))))) 
    20         if canonical is not None: 
    21             events[0].canonical = canonical 
    22         #self._dump(filename, events) 
    23         writer = StringIO.StringIO() 
    24         emitter = Emitter(writer) 
    25         for event in events: 
    26             emitter.emit(event) 
    27         data = writer.getvalue() 
     19        events = list(parse(file(filename, 'rb'))) 
     20        #self._dump(filename, events, canonical) 
     21        stream = StringIO.StringIO() 
     22        emit(events, stream, canonical=canonical) 
     23        data = stream.getvalue() 
    2824        new_events = list(parse(data)) 
    2925        for event, new_event in zip(events, new_events): 
     
    3935                self.failUnlessEqual(event.value, new_event.value) 
    4036 
    41     def _dump(self, filename, events): 
    42         writer = sys.stdout 
    43         emitter = Emitter(writer) 
     37    def _dump(self, filename, events, canonical): 
    4438        print "="*30 
    4539        print "ORIGINAL DOCUMENT:" 
     
    4741        print '-'*30 
    4842        print "EMITTED DOCUMENT:" 
    49         for event in events: 
    50             emitter.emit(event) 
     43        emit(events, sys.stdout, canonical=canonical) 
    5144         
    5245TestEmitter.add_tests('testEmitterOnData', '.canonical', '.data') 
    53 #TestEmitter.add_tests('testEmitterOnCanonicalNormally', '.canonical') 
    54 #TestEmitter.add_tests('testEmitterOnCanonicalCanonically', '.canonical') 
     46TestEmitter.add_tests('testEmitterOnCanonicalNormally', '.canonical') 
     47TestEmitter.add_tests('testEmitterOnCanonicalCanonically', '.canonical') 
    5548 
    56 class EventsConstructor(Constructor): 
     49class EventsLoader(Loader): 
    5750 
    5851    def construct_event(self, node): 
     
    6760            mapping.setdefault('tag', None) 
    6861        if class_name == 'ScalarEvent': 
     62            mapping.setdefault('implicit', False) 
    6963            mapping.setdefault('value', '') 
    7064        value = getattr(yaml, class_name)(**mapping) 
    7165        return value 
    7266 
    73 EventsConstructor.add_constructor(None, EventsConstructor.construct_event) 
     67EventsLoader.add_constructor(None, EventsLoader.construct_event) 
    7468 
    7569class TestEmitterEvents(test_appliance.TestAppliance): 
    7670 
    7771    def _testEmitterEvents(self, test_name, events_filename): 
    78         events = list(load(file(events_filename, 'rb'), Constructor=EventsConstructor)) 
     72        events = list(load(file(events_filename, 'rb'), Loader=EventsLoader)) 
    7973        #self._dump(events_filename, events) 
    80         writer = StringIO.StringIO() 
    81         emitter = Emitter(writer) 
    82         for event in events: 
    83             emitter.emit(event) 
    84         data = writer.getvalue() 
     74        stream = StringIO.StringIO() 
     75        emit(events, stream) 
     76        data = stream.getvalue() 
    8577        new_events = list(parse(data)) 
    8678        self.failUnlessEqual(len(events), len(new_events)) 
     
    9789 
    9890    def _dump(self, events_filename, events): 
    99         writer = sys.stdout 
    100         emitter = Emitter(writer) 
    10191        print "="*30 
    10292        print "EVENTS:" 
     
    10494        print '-'*30 
    10595        print "OUTPUT:" 
    106         for event in events: 
    107             emitter.emit(event) 
     96        emit(events, sys.stdout) 
    10897         
    10998TestEmitterEvents.add_tests('testEmitterEvents', '.events') 
  • pyyaml/trunk/tests/test_errors.py

    r59 r136  
    1616    def _load(self, filename): 
    1717        try: 
    18             reader = Reader(file(filename, 'rb')) 
    19             scanner = Scanner(reader) 
    20             parser = Parser(scanner) 
    21             composer = Composer(parser) 
    22             resolver = Resolver(composer) 
    23             constructor = Constructor(resolver) 
    24             return list(constructor) 
     18            return list(load_all(file(filename, 'rb'))) 
    2519        except YAMLError, exc: 
    2620        #except ScannerError, exc: 
     
    3428    def _load_string(self, filename): 
    3529        try: 
    36             reader = Reader(file(filename, 'rb').read()) 
    37             scanner = Scanner(reader) 
    38             parser = Parser(scanner) 
    39             composer = Composer(parser) 
    40             resolver = Resolver(composer) 
    41             constructor = Constructor(resolver) 
    42             return list(constructor) 
     30            return list(load_all(file(filename, 'rb').read())) 
    4331        except YAMLError, exc: 
    4432        #except ScannerError, exc: 
  • pyyaml/trunk/tests/test_representer.py

    r133 r136  
    1313from yaml import * 
    1414 
    15 class MyConstructor(Constructor): 
     15class MyLoader(Loader): 
    1616    pass 
    17 class MyRepresenter(Representer): 
     17class MyDumper(Dumper): 
    1818    pass 
    1919 
     
    3939class MyTestClass2(MyTestClass1, YAMLObject): 
    4040 
    41     yaml_constructor = MyConstructor 
     41    yaml_loader = MyLoader 
     42    yaml_dumper = MyDumper 
    4243    yaml_tag = "!tag2" 
    4344 
     
    6869    to_yaml = classmethod(to_yaml) 
    6970 
    70 MyConstructor.add_constructor("!tag1", construct1) 
    71 MyRepresenter.add_representer(MyTestClass1, represent1) 
     71MyLoader.add_constructor("!tag1", construct1) 
     72MyDumper.add_representer(MyTestClass1, represent1) 
     73 
     74class YAMLObject1(YAMLObject): 
     75    yaml_loader = MyLoader 
     76    yaml_dumper = MyDumper 
     77    yaml_tag = '!foo' 
     78    yaml_flow_style = True 
     79 
     80    def __init__(self, my_parameter=None, my_another_parameter=None): 
     81        self.my_parameter = my_parameter 
     82        self.my_another_parameter = my_another_parameter 
     83 
     84    def __eq__(self, other): 
     85        if isinstance(other, YAMLObject1): 
     86            return self.__class__, self.__dict__ == other.__class__, other.__dict__ 
     87        else: 
     88            return False 
    7289 
    7390class TestTypeRepresenter(test_appliance.TestAppliance): 
    7491 
    7592    def _testTypes(self, test_name, data_filename, code_filename): 
    76         natives1 = eval(file(code_filename, 'rb').read()) 
    77         natives2 = None 
     93        data1 = eval(file(code_filename, 'rb').read()) 
     94        data2 = None 
    7895        output = None 
    7996        try: 
    80             output = dump(natives1, Representer=MyRepresenter) 
    81             natives2 = load(output, Constructor=MyConstructor) 
     97            output = dump(data1, Dumper=MyDumper) 
     98            data2 = load(output, Loader=MyLoader) 
    8299            try: 
    83                 self.failUnlessEqual(natives1, natives2) 
     100                self.failUnlessEqual(data1, data2) 
    84101            except AssertionError: 
    85                 if isinstance(natives1, dict): 
    86                     natives1 = natives1.items() 
    87                     natives1.sort() 
    88                     natives1 = repr(natives1) 
    89                     natives2 = natives2.items() 
    90                     natives2.sort() 
    91                     natives2 = repr(natives2) 
    92                 if natives1 != natives2: 
     102                if isinstance(data1, dict): 
     103                    data1 = data1.items() 
     104                    data1.sort() 
     105                    data1 = repr(data1) 
     106                    data2 = data2.items() 
     107                    data2.sort() 
     108                    data2 = repr(data2) 
     109                if data1 != data2: 
    93110                    raise 
    94111        except: 
     
    96113            print "OUTPUT:" 
    97114            print output 
    98             print "NATIVES1:", natives1 
    99             print "NATIVES2:", natives2 
     115            print "NATIVES1:", data1 
     116            print "NATIVES2:", data2 
    100117            raise 
    101118 
  • pyyaml/trunk/tests/test_structure.py

    r130 r136  
    1010        node2 = eval(file(structure_filename, 'rb').read()) 
    1111        try: 
    12             parser = Parser(Scanner(Reader(file(data_filename, 'rb')))) 
     12            loader = Loader(file(data_filename, 'rb')) 
    1313            node1 = [] 
    14             while not parser.check(StreamEndEvent): 
    15                 if not parser.check(StreamStartEvent, DocumentStartEvent, DocumentEndEvent): 
    16                     node1.append(self._convert(parser)) 
     14            while not loader.check_event(StreamEndEvent): 
     15                if not loader.check_event(StreamStartEvent, DocumentStartEvent, DocumentEndEvent): 
     16                    node1.append(self._convert(loader)) 
    1717                else: 
    18                     parser.get() 
    19             parser.get() 
     18                    loader.get_event() 
     19            loader.get_event() 
    2020            if len(node1) == 1: 
    2121                node1 = node1[0] 
     
    2929            raise 
    3030 
    31     def _convert(self, parser): 
    32         if parser.check(ScalarEvent): 
    33             event = parser.get() 
     31    def _convert(self, loader): 
     32        if loader.check_event(ScalarEvent): 
     33            event = loader.get_event() 
    3434            if event.tag or event.anchor or event.value: 
    3535                return True 
    3636            else: 
    3737                return None 
    38         elif parser.check(SequenceStartEvent): 
    39             parser.get() 
     38        elif loader.check_event(SequenceStartEvent): 
     39            loader.get_event() 
    4040            sequence = [] 
    41             while not parser.check(SequenceEndEvent): 
    42                 sequence.append(self._convert(parser)) 
    43             parser.get() 
     41            while not loader.check_event(SequenceEndEvent): 
     42                sequence.append(self._convert(loader)) 
     43            loader.get_event() 
    4444            return sequence 
    45         elif parser.check(MappingStartEvent): 
    46             parser.get() 
     45        elif loader.check_event(MappingStartEvent): 
     46            loader.get_event() 
    4747            mapping = [] 
    48             while not parser.check(MappingEndEvent): 
    49                 key = self._convert(parser) 
    50                 value = self._convert(parser) 
     48            while not loader.check_event(MappingEndEvent): 
     49                key = self._convert(loader) 
     50                value = self._convert(loader) 
    5151                mapping.append((key, value)) 
    52             parser.get() 
     52            loader.get_event() 
    5353            return mapping 
    54         elif parser.check(AliasEvent): 
    55             parser.get() 
     54        elif loader.check_event(AliasEvent): 
     55            loader.get_event() 
    5656            return '*' 
    5757        else: 
    58             parser.get() 
     58            loader.get_event() 
    5959            return '?' 
    6060 
     
    6767        events2 = None 
    6868        try: 
    69             parser = Parser(Scanner(Reader(file(data_filename, 'rb')))) 
    70             events1 = list(iter(parser)) 
    71             canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read()) 
    72             events2 = canonical.parse() 
     69            events1 = list(parse(file(data_filename, 'rb'))) 
     70            events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb'))) 
    7371            self._compare(events1, events2) 
    7472        except: 
     
    106104        nodes2 = None 
    107105        try: 
    108             resolver1 = Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb')))))) 
    109             nodes1 = list(iter(resolver1)) 
    110             canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read()) 
    111             canonical.parse() 
    112             resolver2 = Resolver(Composer(canonical)) 
    113             nodes2 = list(iter(resolver2)) 
     106            nodes1 = list(compose_all(file(data_filename, 'rb'))) 
     107            nodes2 = list(test_appliance.canonical_compose_all(file(canonical_filename, 'rb'))) 
    114108            self.failUnlessEqual(len(nodes1), len(nodes2)) 
    115109            for node1, node2 in zip(nodes1, nodes2): 
     
    148142TestResolver.add_tests('testResolver', '.data', '.canonical') 
    149143 
    150 class MyConstructor(Constructor): 
     144class MyConstructor: 
    151145 
    152146    def construct_sequence(self, node): 
     
    158152        return pairs 
    159153 
    160 MyConstructor.add_constructor(None, MyConstructor.construct_scalar) 
     154    def construct_undefined(self, node): 
     155        return self.construct_scalar(node) 
     156 
     157class MyLoader(MyConstructor, Loader): 
     158    pass 
     159MyLoader.add_constructor(None, MyLoader.construct_undefined) 
     160 
     161class MyCanonicalLoader(MyConstructor, test_appliance.CanonicalLoader): 
     162    pass 
     163MyCanonicalLoader.add_constructor(None, MyCanonicalLoader.construct_undefined) 
    161164 
    162165class TestConstructor(test_appliance.TestAppliance): 
    163166 
    164167    def _testConstructor(self, test_name, data_filename, canonical_filename): 
    165         natives1 = None 
    166         natives2 = None 
    167         try: 
    168             constructor1 = MyConstructor(Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb'))))))) 
    169             natives1 = list(iter(constructor1)) 
    170             canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read()) 
    171             canonical.parse() 
    172             constructor2 = MyConstructor(Resolver(Composer(canonical))) 
    173             natives2 = list(iter(constructor2)) 
    174             self.failUnlessEqual(natives1, natives2) 
     168        data1 = None 
     169        data2 = None 
     170        try: 
     171            data1 = list(load_all(file(data_filename, 'rb'), Loader=MyLoader)) 
     172            data2 = list(load_all(file(canonical_filename, 'rb'), Loader=MyCanonicalLoader)) 
     173            self.failUnlessEqual(data1, data2) 
    175174        except: 
    176175            print 
     
    179178            print "DATA2:" 
    180179            print file(canonical_filename, 'rb').read() 
    181             print "NATIVES1:", natives1 
    182             print "NATIVES2:", natives2 
     180            print "NATIVES1:", data1 
     181            print "NATIVES2:", data2 
    183182            raise 
    184183 
     
    191190        events2 = None 
    192191        try: 
    193             parser = Parser(Scanner(Reader(file(canonical_filename, 'rb')))) 
    194             events1 = list(iter(parser)) 
    195             canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read()) 
    196             events2 = canonical.parse() 
     192            events1 = list(parse(file(canonical_filename, 'rb'))) 
     193            events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb'))) 
    197194            self._compare(events1, events2) 
    198195        except: 
  • pyyaml/trunk/tests/test_tokens.py

    r118 r136  
    22import test_appliance 
    33 
    4 from yaml.reader import * 
    5 from yaml.tokens import * 
    6 from yaml.scanner import * 
     4from yaml import * 
    75 
    86class TestTokens(test_appliance.TestAppliance): 
     
    5250        tokens2 = file(tokens_filename, 'rb').read().split() 
    5351        try: 
    54             scanner = Scanner(Reader(file(data_filename, 'rb'))) 
    5552            tokens1 = [] 
    56             for token in scanner: 
     53            for token in scan(file(data_filename, 'rb')): 
    5754                if not isinstance(token, (StreamStartToken, StreamEndToken)): 
    5855                    tokens1.append(token) 
     
    7572            tokens = None 
    7673            try: 
    77                 scanner = Scanner(Reader(file(filename, 'rb'))) 
    7874                tokens = [] 
    79                 for token in scanner: 
     75                for token in scan(file(filename, 'rb')): 
    8076                    if not isinstance(token, (StreamStartToken, StreamEndToken)): 
    8177                        tokens.append(token.__class__.__name__) 
Note: See TracChangeset for help on using the changeset viewer.