Changeset 137


Ignore:
Timestamp:
04/16/06 19:45:21 (8 years ago)
Author:
xi
Message:

Refactor resolver.

Location:
pyyaml/trunk
Files:
2 added
18 edited
2 moved

Legend:

Unmodified
Added
Removed
  • pyyaml/trunk/lib/yaml/__init__.py

    r136 r137  
    1212from representer import * 
    1313 
    14 from detector import * 
     14from resolver import * 
    1515 
    1616from tokens import * 
     
    197197    return dump_all([data], stream, Dumper=SafeDumper, **kwds) 
    198198 
    199 def add_detector(tag, regexp, first=None, Loader=Loader, Dumper=Dumper): 
     199def add_implicit_detector(tag, regexp, first=None, 
     200        Loader=Loader, Dumper=Dumper): 
    200201    """ 
    201202    Add an implicit scalar detector. 
     
    204205    first is a sequence of possible initial characters or None. 
    205206    """ 
    206     Loader.add_detector(tag, regexp, first) 
    207     Dumper.add_detector(tag, regexp, first) 
    208  
    209 def add_resolver(tag, path, Loader=Loader): 
     207    Loader.add_implicit_resolver(tag, regexp, first) 
     208    Dumper.add_implicit_resolver(tag, regexp, first) 
     209 
     210def add_path_resolver(tag, path, kind=None, Loader=Loader, Dumper=Dumper): 
    210211    """ 
    211212    Add a path based resolver for the given tag. 
     
    214215    Keys can be string values, integers, or None. 
    215216    """ 
    216     Loader.add_resolver(tag, path) 
     217    Loader.add_path_resolver(tag, path, kind) 
     218    Dumper.add_path_resolver(tag, path, kind) 
    217219 
    218220def add_constructor(tag, constructor, Loader=Loader): 
     
    232234    """ 
    233235    Loader.add_multi_constructor(tag_prefix, multi_constructor) 
     236 
     237def add_representer(data_type, representer, Dumper=Dumper): 
     238    """ 
     239    Add a representer for the given type. 
     240    Representer is a function accepting a Dumper instance 
     241    and an instance of the given data type 
     242    and producing the corresponding representation node. 
     243    """ 
     244    Dumper.add_representer(data_type, representer) 
    234245 
    235246class YAMLObjectMetaclass(type): 
  • pyyaml/trunk/lib/yaml/composer.py

    r136 r137  
    11 
    2 __all__ = ['BaseComposer', 'Composer', 'ComposerError'] 
     2__all__ = ['Composer', 'ComposerError'] 
    33 
    44from error import MarkedYAMLError 
     
    99    pass 
    1010 
    11 class BaseComposer: 
    12  
    13     yaml_resolvers = {} 
     11class Composer: 
    1412 
    1513    def __init__(self): 
    1614        self.all_anchors = {} 
    1715        self.complete_anchors = {} 
    18         self.resolver_tags = [] 
    19         self.resolver_paths = [] 
    2016 
    2117    def check_node(self): 
     
    4339 
    4440        # Compose the root node. 
    45         node = self.compose_node([]) 
     41        node = self.compose_node(None, None) 
    4642 
    4743        # Drop the DOCUMENT-END event. 
     
    5046        self.all_anchors = {} 
    5147        self.complete_anchors = {} 
    52         self.resolver_tags = [] 
    53         self.resolver_paths = [] 
    5448        return node 
    5549 
    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): 
     50    def compose_node(self, parent, index): 
    8851        if self.check_event(AliasEvent): 
    8952            event = self.get_event() 
     
    9962                        event.start_mark) 
    10063            return self.complete_anchors[anchor] 
    101         self.increase_resolver_depth(path) 
    10264        event = self.peek_event() 
    10365        anchor = event.anchor 
     
    10870                        "second occurence", event.start_mark) 
    10971            self.all_anchors[anchor] = event 
     72        self.descend_resolver(parent, index) 
    11073        if self.check_event(ScalarEvent): 
    111             node = self.compose_scalar_node(path) 
     74            node = self.compose_scalar_node() 
    11275        elif self.check_event(SequenceStartEvent): 
    113             node = self.compose_sequence_node(path) 
     76            node = self.compose_sequence_node() 
    11477        elif self.check_event(MappingStartEvent): 
    115             node = self.compose_mapping_node(path) 
     78            node = self.compose_mapping_node() 
    11679        if anchor is not None: 
    11780            self.complete_anchors[anchor] = node 
    118         self.decrease_resolver_depth() 
     81        self.ascend_resolver() 
    11982        return node 
    12083 
    121     def compose_scalar_node(self, path): 
     84    def compose_scalar_node(self): 
    12285        event = self.get_event() 
    123         tag = self.resolve_scalar(path, event.tag, event.implicit, event.value) 
     86        tag = event.tag 
     87        if tag is None or tag == u'!': 
     88            tag = self.resolve(ScalarNode, event.value, event.implicit) 
    12489        return ScalarNode(tag, event.value, 
    12590                event.start_mark, event.end_mark, style=event.style) 
    12691 
    127     def compose_sequence_node(self, path): 
     92    def compose_sequence_node(self): 
    12893        start_event = self.get_event() 
    129         tag = self.resolve_sequence(path, start_event.tag) 
     94        tag = start_event.tag 
     95        if tag is None or tag == u'!': 
     96            tag = self.resolve(SequenceNode, None, start_event.implicit) 
    13097        node = SequenceNode(tag, [], 
    13198                start_event.start_mark, None, 
     
    133100        index = 0 
    134101        while not self.check_event(SequenceEndEvent): 
    135             node.value.append(self.compose_node(path+[(node, index)])) 
     102            node.value.append(self.compose_node(node, index)) 
    136103            index += 1 
    137104        end_event = self.get_event() 
     
    139106        return node 
    140107 
    141     def compose_mapping_node(self, path): 
     108    def compose_mapping_node(self): 
    142109        start_event = self.get_event() 
    143         tag = self.resolve_mapping(path, start_event.tag) 
     110        tag = start_event.tag 
     111        if tag is None or tag == u'!': 
     112            tag = self.resolve(MappingNode, None, start_event.implicit) 
    144113        node = MappingNode(tag, {}, 
    145114                start_event.start_mark, None, 
     
    147116        while not self.check_event(MappingEndEvent): 
    148117            key_event = self.peek_event() 
    149             item_key = self.compose_node(path+[(node, None)]) 
    150             item_value = self.compose_node(path+[(node, item_key)]) 
     118            item_key = self.compose_node(node, None) 
    151119            if item_key in node.value: 
    152120                raise ComposerError("while composing a mapping", start_event.start_mark, 
    153121                        "found duplicate key", key_event.start_mark) 
     122            item_value = self.compose_node(node, item_key) 
    154123            node.value[item_key] = item_value 
    155124        end_event = self.get_event() 
     
    157126        return node 
    158127 
    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  
    188 class Composer(BaseComposer): 
    189     pass 
    190  
  • pyyaml/trunk/lib/yaml/dumper.py

    r136 r137  
    55from serializer import * 
    66from representer import * 
    7 from detector import * 
     7from resolver import * 
    88 
    9 class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseDetector): 
     9class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): 
    1010 
    1111    def __init__(self, stream, 
     
    2121                version=version, tags=tags) 
    2222        Representer.__init__(self) 
    23         Detector.__init__(self) 
     23        Resolver.__init__(self) 
    2424 
    25 class SafeDumper(Emitter, Serializer, SafeRepresenter, Detector): 
     25class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver): 
    2626 
    2727    def __init__(self, stream, 
     
    3737                version=version, tags=tags) 
    3838        SafeRepresenter.__init__(self) 
    39         Detector.__init__(self) 
     39        Resolver.__init__(self) 
    4040 
    41 class Dumper(Emitter, Serializer, Representer, Detector): 
     41class Dumper(Emitter, Serializer, Representer, Resolver): 
    4242 
    4343    def __init__(self, stream, 
     
    5353                version=version, tags=tags) 
    5454        Representer.__init__(self) 
    55         Detector.__init__(self) 
     55        Resolver.__init__(self) 
    5656 
  • pyyaml/trunk/lib/yaml/emitter.py

    r136 r137  
    461461            if self.style is None: 
    462462                self.style = self.choose_scalar_style() 
    463             if self.style == '': 
     463            if ((not self.canonical or tag is None) and 
     464                ((self.style == '' and self.event.implicit[0]) 
     465                        or (self.style != '' and self.event.implicit[1]))): 
    464466                self.prepared_tag = None 
    465467                return 
    466             if self.event.implicit and not tag: 
     468            if self.event.implicit[0] and not tag: 
    467469                tag = u'!' 
    468470                self.prepared_tag = None 
     471        else: 
     472            if (not self.canonical or tag is None) and self.event.implicit: 
     473                self.prepared_tag = None 
     474                return 
    469475        if not tag: 
    470             self.prepared_tag = None 
    471             return 
     476            raise EmitterError("tag is not specified") 
    472477        if self.prepared_tag is None: 
    473478            self.prepared_tag = self.prepare_tag(tag) 
     
    481486        if self.event.style == '"' or self.canonical: 
    482487            return '"' 
    483         if not self.event.style and self.event.implicit: 
     488        if not self.event.style and self.event.implicit[0]: 
    484489            if (not (self.simple_key_context and 
    485490                    (self.analysis.empty or self.analysis.multiline)) 
  • pyyaml/trunk/lib/yaml/events.py

    r136 r137  
    77        self.end_mark = end_mark 
    88    def __repr__(self): 
    9         attributes = [key for key in ['anchor', 'tag', 'value'] 
     9        attributes = [key for key in ['anchor', 'tag', 'implicit', 'value'] 
    1010                if hasattr(self, key)] 
    1111        arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) 
     
    2020 
    2121class CollectionStartEvent(NodeEvent): 
    22     def __init__(self, anchor, tag, start_mark=None, end_mark=None, 
     22    def __init__(self, anchor, tag, implicit, start_mark=None, end_mark=None, 
    2323            flow_style=None): 
    2424        self.anchor = anchor 
    2525        self.tag = tag 
     26        self.implicit = implicit 
    2627        self.start_mark = start_mark 
    2728        self.end_mark = end_mark 
  • pyyaml/trunk/lib/yaml/loader.py

    r136 r137  
    77from composer import * 
    88from constructor import * 
    9 from detector import * 
     9from resolver import * 
    1010 
    11 class BaseLoader(Reader, Scanner, Parser, 
    12         BaseComposer, BaseConstructor, BaseDetector): 
     11class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, BaseResolver): 
    1312 
    1413    def __init__(self, stream): 
     
    1615        Scanner.__init__(self) 
    1716        Parser.__init__(self) 
    18         BaseComposer.__init__(self) 
     17        Composer.__init__(self) 
    1918        BaseConstructor.__init__(self) 
    20         BaseDetector.__init__(self) 
     19        BaseResolver.__init__(self) 
    2120 
    22 class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, Detector): 
     21class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, Resolver): 
    2322 
    2423    def __init__(self, stream): 
     
    2827        Composer.__init__(self) 
    2928        SafeConstructor.__init__(self) 
    30         Detector.__init__(self) 
     29        Resolver.__init__(self) 
    3130 
    32 class Loader(Reader, Scanner, Parser, Composer, Constructor, Detector): 
     31class Loader(Reader, Scanner, Parser, Composer, Constructor, Resolver): 
    3332 
    3433    def __init__(self, stream): 
     
    3837        Composer.__init__(self) 
    3938        Constructor.__init__(self) 
    40         Detector.__init__(self) 
     39        Resolver.__init__(self) 
    4140 
  • pyyaml/trunk/lib/yaml/parser.py

    r136 r137  
    267267            event = None 
    268268            collection_events = None 
     269            implicit = (tag is None or tag == u'!') 
    269270            if indentless_sequence and self.check_token(BlockEntryToken): 
    270271                end_mark = self.peek_token().end_mark 
    271                 event = SequenceStartEvent(anchor, tag, start_mark, end_mark) 
     272                event = SequenceStartEvent(anchor, tag, implicit, 
     273                        start_mark, end_mark) 
    272274                collection_events = self.parse_indentless_sequence() 
    273275            else: 
     
    275277                    token = self.get_token() 
    276278                    end_mark = token.end_mark 
    277                     implicit = ((tag is None or tag == u'!') and token.implicit) 
     279                    if (token.plain and tag is None) or tag == u'!': 
     280                        implicit = (True, False) 
     281                    elif tag is None: 
     282                        implicit = (False, True) 
     283                    else: 
     284                        implicit = (False, False) 
    278285                    event = ScalarEvent(anchor, tag, implicit, token.value, 
    279286                            start_mark, end_mark, style=token.style) 
    280287                elif self.check_token(FlowSequenceStartToken): 
    281288                    end_mark = self.peek_token().end_mark 
    282                     event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 
    283                             flow_style=True) 
     289                    event = SequenceStartEvent(anchor, tag, implicit, 
     290                            start_mark, end_mark, flow_style=True) 
    284291                    collection_events = self.parse_flow_sequence() 
    285292                elif self.check_token(FlowMappingStartToken): 
    286293                    end_mark = self.peek_token().end_mark 
    287                     event = MappingStartEvent(anchor, tag, start_mark, end_mark, 
    288                             flow_style=True) 
     294                    event = MappingStartEvent(anchor, tag, implicit, 
     295                            start_mark, end_mark, flow_style=True) 
    289296                    collection_events = self.parse_flow_mapping() 
    290297                elif block and self.check_token(BlockSequenceStartToken): 
    291298                    end_mark = self.peek_token().start_mark 
    292                     event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 
    293                             flow_style=False) 
     299                    event = SequenceStartEvent(anchor, tag, implicit, 
     300                            start_mark, end_mark, flow_style=False) 
    294301                    collection_events = self.parse_block_sequence() 
    295302                elif block and self.check_token(BlockMappingStartToken): 
    296303                    end_mark = self.peek_token().start_mark 
    297                     event = MappingStartEvent(anchor, tag, start_mark, end_mark, 
    298                             flow_style=False) 
     304                    event = MappingStartEvent(anchor, tag, implicit, 
     305                            start_mark, end_mark, flow_style=False) 
    299306                    collection_events = self.parse_block_mapping() 
    300307                elif anchor is not None or tag is not None: 
    301308                    # Empty scalars are allowed even if a tag or an anchor is 
    302309                    # specified. 
    303                     implicit = (tag is None or tag == u'!') 
    304                     event = ScalarEvent(anchor, tag, implicit, u'', 
     310                    event = ScalarEvent(anchor, tag, (implicit, False), u'', 
    305311                            start_mark, end_mark) 
    306312                else: 
     
    397403            if self.check_token(KeyToken): 
    398404                token = self.get_token() 
    399                 yield MappingStartEvent(None, None, # u'!', 
     405                yield MappingStartEvent(None, None, True, 
    400406                        token.start_mark, token.end_mark, 
    401407                        flow_style=True) 
     
    475481 
    476482    def process_empty_scalar(self, mark): 
    477         return ScalarEvent(None, None, True, u'', mark, mark) 
    478  
     483        return ScalarEvent(None, None, (True, False), u'', mark, mark) 
     484 
  • pyyaml/trunk/lib/yaml/representer.py

    r136 r137  
    55from error import * 
    66from nodes import * 
    7 from detector import * 
    87 
    98try: 
  • pyyaml/trunk/lib/yaml/resolver.py

    r136 r137  
    11 
    2 __all__ = ['BaseDetector', 'Detector'] 
     2__all__ = ['BaseResolver', 'Resolver'] 
     3 
     4from error import * 
     5from nodes import * 
    36 
    47import re 
    58 
    6 class BaseDetector: 
     9class ResolverError(YAMLError): 
     10    pass 
     11 
     12class BaseResolver: 
    713 
    814    DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' 
     
    1016    DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' 
    1117 
    12     yaml_detectors = {} 
     18    yaml_implicit_resolvers = {} 
     19    yaml_path_resolvers = {} 
    1320 
    1421    def __init__(self): 
    15         pass 
    16  
    17     def add_detector(cls, tag, regexp, first): 
    18         if not 'yaml_detectors' in cls.__dict__: 
    19             cls.yaml_detectors = cls.yaml_detectors.copy() 
     22        self.resolver_exact_paths = [] 
     23        self.resolver_prefix_paths = [] 
     24 
     25    def add_implicit_resolver(cls, tag, regexp, first): 
     26        if not 'yaml_implicit_resolvers' in cls.__dict__: 
     27            cls.yaml_implicit_resolvers = cls.yaml_implicit_resolvers.copy() 
    2028        for ch in first: 
    21             cls.yaml_detectors.setdefault(ch, []).append((tag, regexp)) 
    22     add_detector = classmethod(add_detector) 
    23  
    24     def detect(self, value): 
    25         if value == u'': 
    26             detectors = self.yaml_detectors.get(u'', []) 
     29            cls.yaml_implicit_resolvers.setdefault(ch, []).append((tag, regexp)) 
     30    add_implicit_resolver = classmethod(add_implicit_resolver) 
     31 
     32    def add_path_resolver(cls, tag, path, kind=None): 
     33        if not 'yaml_path_resolvers' in cls.__dict__: 
     34            cls.yaml_path_resolvers = cls.yaml_path_resolvers.copy() 
     35        new_path = [] 
     36        for element in path: 
     37            if isinstance(element, (list, tuple)): 
     38                if len(element) == 2: 
     39                    node_check, index_check = element 
     40                elif len(element) == 1: 
     41                    node_check = element[0] 
     42                    index_check = True 
     43                else: 
     44                    raise ResolverError("Invalid path element: %s" % element) 
     45            else: 
     46                node_check = None 
     47                index_check = element 
     48            if node_check is str: 
     49                node_check = ScalarNode 
     50            elif node_check is list: 
     51                node_check = SequenceNode 
     52            elif node_check is map: 
     53                node_check = MappingNode 
     54            elif node_check not in [ScalarNode, SequenceNode, MappingNode]  \ 
     55                    and not isinstance(node_check, basestring)  \ 
     56                    and node_check is not None: 
     57                raise ResolverError("Invalid node checker: %s" % node_check) 
     58            if not isinstance(index_check, (basestring, int))   \ 
     59                    and index_check is not None: 
     60                raise ResolverError("Invalid index checker: %s" % index_check) 
     61            new_path.append((node_check, index_check)) 
     62        if kind is str: 
     63            kind = ScalarNode 
     64        elif kind is list: 
     65            kind = SequenceNode 
     66        elif kind is map: 
     67            kind = MappingNode 
     68        elif kind not in [ScalarNode, SequenceNode, MappingNode]    \ 
     69                and kind is not None: 
     70            raise ResolverError("Invalid node kind: %s" % kind) 
     71        cls.yaml_path_resolvers[tuple(new_path), kind] = tag 
     72    add_path_resolver = classmethod(add_path_resolver) 
     73 
     74    def descend_resolver(self, current_node, current_index): 
     75        exact_paths = {} 
     76        prefix_paths = [] 
     77        if current_node: 
     78            depth = len(self.resolver_prefix_paths) 
     79            for path, kind in self.resolver_prefix_paths[-1]: 
     80                if self.check_resolver_prefix(depth, path, kind, 
     81                        current_node, current_index): 
     82                    if len(path) > depth: 
     83                        prefix_paths.append((path, kind)) 
     84                    else: 
     85                        exact_paths[kind] = self.yaml_path_resolvers[path, kind] 
    2786        else: 
    28             detectors = self.yaml_detectors.get(value[0], []) 
    29         detectors += self.yaml_detectors.get(None, []) 
    30         for tag, regexp in detectors: 
    31             if regexp.match(value): 
    32                 return tag 
    33  
    34 class Detector(BaseDetector): 
     87            for path, kind in self.yaml_path_resolvers: 
     88                if not path: 
     89                    exact_paths[kind] = self.yaml_path_resolvers[path, kind] 
     90                else: 
     91                    prefix_paths.append((path, kind)) 
     92        self.resolver_exact_paths.append(exact_paths) 
     93        self.resolver_prefix_paths.append(prefix_paths) 
     94 
     95    def ascend_resolver(self): 
     96        self.resolver_exact_paths.pop() 
     97        self.resolver_prefix_paths.pop() 
     98 
     99    def check_resolver_prefix(self, depth, path, kind, 
     100            current_node, current_index): 
     101        node_check, index_check = path[depth-1] 
     102        if isinstance(node_check, basestring): 
     103            if current_node.tag != node_check: 
     104                return 
     105        elif node_check is not None: 
     106            if not isinstance(current_node, node_check): 
     107                return 
     108        if index_check is True and current_index is not None: 
     109            return 
     110        if index_check in [False, None] and current_index is None: 
     111            return 
     112        if isinstance(index_check, basestring): 
     113            if not (isinstance(current_index, ScalarNode) 
     114                    and index_check == current_index.value): 
     115                return 
     116        elif isinstance(index_check, int): 
     117            if index_check != current_index: 
     118                return 
     119        return True 
     120 
     121    def resolve(self, kind, value, implicit): 
     122        if kind is ScalarNode and implicit[0]: 
     123            if value == u'': 
     124                resolvers = self.yaml_implicit_resolvers.get(u'', []) 
     125            else: 
     126                resolvers = self.yaml_implicit_resolvers.get(value[0], []) 
     127            resolvers += self.yaml_implicit_resolvers.get(None, []) 
     128            for tag, regexp in resolvers: 
     129                if regexp.match(value): 
     130                    return tag 
     131            implicit = implicit[1] 
     132        exact_paths = self.resolver_exact_paths[-1] 
     133        if kind in exact_paths: 
     134            return exact_paths[kind] 
     135        if None in exact_paths: 
     136            return exact_paths[None] 
     137        if kind is ScalarNode: 
     138            return self.DEFAULT_SCALAR_TAG 
     139        elif kind is SequenceNode: 
     140            return self.DEFAULT_SEQUENCE_TAG 
     141        elif kind is MappingNode: 
     142            return self.DEFAULT_MAPPING_TAG 
     143 
     144class Resolver(BaseResolver): 
    35145    pass 
    36146 
    37 Detector.add_detector( 
     147Resolver.add_implicit_resolver( 
    38148        u'tag:yaml.org,2002:bool', 
    39149        re.compile(ur'''^(?:yes|Yes|YES|n|N|no|No|NO 
     
    42152        list(u'yYnNtTfFoO')) 
    43153 
    44 Detector.add_detector( 
     154Resolver.add_implicit_resolver( 
    45155        u'tag:yaml.org,2002:float', 
    46156        re.compile(ur'''^(?:[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*(?:[eE][-+][0-9]+)? 
     
    50160        list(u'-+0123456789.')) 
    51161 
    52 Detector.add_detector( 
     162Resolver.add_implicit_resolver( 
    53163        u'tag:yaml.org,2002:int', 
    54164        re.compile(ur'''^(?:[-+]?0b[0-1_]+ 
     
    59169        list(u'-+0123456789')) 
    60170 
    61 Detector.add_detector( 
     171Resolver.add_implicit_resolver( 
    62172        u'tag:yaml.org,2002:merge', 
    63173        re.compile(ur'^(?:<<)$'), 
    64174        ['<']) 
    65175 
    66 Detector.add_detector( 
     176Resolver.add_implicit_resolver( 
    67177        u'tag:yaml.org,2002:null', 
    68178        re.compile(ur'''^(?: ~ 
     
    71181        [u'~', u'n', u'N', u'']) 
    72182 
    73 Detector.add_detector( 
     183Resolver.add_implicit_resolver( 
    74184        u'tag:yaml.org,2002:timestamp', 
    75185        re.compile(ur'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 
     
    80190        list(u'0123456789')) 
    81191 
    82 Detector.add_detector( 
     192Resolver.add_implicit_resolver( 
    83193        u'tag:yaml.org,2002:value', 
    84194        re.compile(ur'^(?:=)$'), 
    85195        ['=']) 
    86196 
    87 # The following detector is only for documentation purposes. It cannot work 
     197# The following resolver is only for documentation purposes. It cannot work 
    88198# because plain scalars cannot start with '!', '&', or '*'. 
    89 Detector.add_detector( 
     199Resolver.add_implicit_resolver( 
    90200        u'tag:yaml.org,2002:yaml', 
    91201        re.compile(ur'^(?:!|&|\*)$'), 
  • pyyaml/trunk/lib/yaml/serializer.py

    r136 r137  
    5252            version=self.use_version, tags=self.use_tags)) 
    5353        self.anchor_node(node) 
    54         self.serialize_node(node) 
     54        self.serialize_node(node, None, None) 
    5555        self.emit(DocumentEndEvent(explicit=self.use_explicit_end)) 
    5656        self.serialized_nodes = {} 
     
    7676        return self.ANCHOR_TEMPLATE % self.last_anchor_id 
    7777 
    78     def serialize_node(self, node): 
     78    def serialize_node(self, node, parent, index): 
    7979        alias = self.anchors[node] 
    8080        if node in self.serialized_nodes: 
     
    8282        else: 
    8383            self.serialized_nodes[node] = True 
     84            self.descend_resolver(parent, index) 
    8485            if isinstance(node, ScalarNode): 
    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)) 
     86                detected_tag = self.resolve(ScalarNode, node.value, (True, False)) 
     87                default_tag = self.resolve(ScalarNode, node.value, (False, True)) 
     88                implicit = (node.tag == detected_tag), (node.tag == default_tag) 
    8989                self.emit(ScalarEvent(alias, node.tag, implicit, node.value, 
    9090                    style=node.style)) 
    9191            elif isinstance(node, SequenceNode): 
    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, 
     92                implicit = (node.tag 
     93                            == self.resolve(SequenceNode, node.value, True)) 
     94                self.emit(SequenceStartEvent(alias, node.tag, implicit, 
    10095                    flow_style=node.flow_style)) 
     96                index = 0 
    10197                for item in node.value: 
    102                     self.serialize_node(item) 
     98                    self.serialize_node(item, node, index) 
     99                    index += 1 
    103100                self.emit(SequenceEndEvent()) 
    104101            elif isinstance(node, MappingNode): 
    105                 tag = node.tag 
    106                 if tag == self.DEFAULT_MAPPING_TAG and not self.canonical: 
    107                     tag = None 
    108                 self.emit(MappingStartEvent(alias, tag, 
     102                implicit = (node.tag 
     103                            == self.resolve(MappingNode, node.value, True)) 
     104                self.emit(MappingStartEvent(alias, node.tag, implicit, 
    109105                    flow_style=node.flow_style)) 
    110106                if hasattr(node.value, 'keys'): 
    111107                    for key in node.value.keys(): 
    112                         self.serialize_node(key) 
    113                         self.serialize_node(node.value[key]) 
     108                        self.serialize_node(key, node, None) 
     109                        self.serialize_node(node.value[key], node, key) 
    114110                else: 
    115111                    for key, value in node.value: 
    116                         self.serialize_node(key) 
    117                         self.serialize_node(value) 
     112                        self.serialize_node(key, node, None) 
     113                        self.serialize_node(value, node, key) 
    118114                self.emit(MappingEndEvent()) 
     115            self.ascend_resolver() 
    119116 
  • pyyaml/trunk/lib/yaml/tokens.py

    r130 r137  
    9696class ScalarToken(Token): 
    9797    id = '<scalar>' 
    98     def __init__(self, value, implicit, start_mark, end_mark, style=None): 
     98    def __init__(self, value, plain, start_mark, end_mark, style=None): 
    9999        self.value = value 
    100         self.implicit = implicit 
     100        self.plain = plain 
    101101        self.start_mark = start_mark 
    102102        self.end_mark = end_mark 
  • pyyaml/trunk/tests/data/documents.events

    r132 r137  
    11- !StreamStart 
    22- !DocumentStart { explicit: false } 
    3 - !Scalar { implicit: true, value: 'data' } 
     3- !Scalar { implicit: [true,false], value: 'data' } 
    44- !DocumentEnd 
    55- !DocumentStart 
    6 - !Scalar { implicit: true } 
     6- !Scalar { implicit: [true,false] } 
    77- !DocumentEnd 
    88- !DocumentStart { version: [1,1], tags: { '!': '!foo', '!yaml!': 'tag:yaml.org,2002:', '!ugly!': '!!!!!!!' } } 
    9 - !Scalar { implicit: true } 
     9- !Scalar { implicit: [true,false] } 
    1010- !DocumentEnd 
    1111- !StreamEnd 
  • pyyaml/trunk/tests/data/mappings.events

    r132 r137  
    33- !DocumentStart 
    44- !MappingStart 
    5 - !Scalar { implicit: true, value: 'key' } 
    6 - !Scalar { implicit: true, value: 'value' } 
    7 - !Scalar { implicit: true, value: 'empty mapping' } 
     5- !Scalar { implicit: [true,true], value: 'key' } 
     6- !Scalar { implicit: [true,true], value: 'value' } 
     7- !Scalar { implicit: [true,true], value: 'empty mapping' } 
    88- !MappingStart 
    99- !MappingEnd 
    10 - !Scalar { implicit: true, value: 'empty mapping with tag' } 
    11 - !MappingStart { tag: '!mytag' } 
     10- !Scalar { implicit: [true,true], value: 'empty mapping with tag' } 
     11- !MappingStart { tag: '!mytag', implicit: false } 
    1212- !MappingEnd 
    13 - !Scalar { implicit: true, value: 'block mapping' } 
     13- !Scalar { implicit: [true,true], value: 'block mapping' } 
    1414- !MappingStart 
    1515- !MappingStart 
    16 - !Scalar { implicit: true, value: 'complex' } 
    17 - !Scalar { implicit: true, value: 'key' } 
    18 - !Scalar { implicit: true, value: 'complex' } 
    19 - !Scalar { implicit: true, value: 'key' } 
     16- !Scalar { implicit: [true,true], value: 'complex' } 
     17- !Scalar { implicit: [true,true], value: 'key' } 
     18- !Scalar { implicit: [true,true], value: 'complex' } 
     19- !Scalar { implicit: [true,true], value: 'key' } 
    2020- !MappingEnd 
    2121- !MappingStart 
    22 - !Scalar { implicit: true, value: 'complex' } 
    23 - !Scalar { implicit: true, value: 'key' } 
     22- !Scalar { implicit: [true,true], value: 'complex' } 
     23- !Scalar { implicit: [true,true], value: 'key' } 
    2424- !MappingEnd 
    2525- !MappingEnd 
    26 - !Scalar { implicit: true, value: 'flow mapping' } 
     26- !Scalar { implicit: [true,true], value: 'flow mapping' } 
    2727- !MappingStart { flow_style: true } 
    28 - !Scalar { implicit: true, value: 'key' } 
    29 - !Scalar { implicit: true, value: 'value' } 
     28- !Scalar { implicit: [true,true], value: 'key' } 
     29- !Scalar { implicit: [true,true], value: 'value' } 
    3030- !MappingStart 
    31 - !Scalar { implicit: true, value: 'complex' } 
    32 - !Scalar { implicit: true, value: 'key' } 
    33 - !Scalar { implicit: true, value: 'complex' } 
    34 - !Scalar { implicit: true, value: 'key' } 
     31- !Scalar { implicit: [true,true], value: 'complex' } 
     32- !Scalar { implicit: [true,true], value: 'key' } 
     33- !Scalar { implicit: [true,true], value: 'complex' } 
     34- !Scalar { implicit: [true,true], value: 'key' } 
    3535- !MappingEnd 
    3636- !MappingStart 
    37 - !Scalar { implicit: true, value: 'complex' } 
    38 - !Scalar { implicit: true, value: 'key' } 
     37- !Scalar { implicit: [true,true], value: 'complex' } 
     38- !Scalar { implicit: [true,true], value: 'key' } 
    3939- !MappingEnd 
    4040- !MappingEnd 
  • pyyaml/trunk/tests/data/scalars.events

    r133 r137  
    33- !DocumentStart 
    44- !MappingStart 
    5 - !Scalar { implicit: true, value: 'empty scalar' } 
    6 - !Scalar { implicit: true, value: '' } 
    7 - !Scalar { implicit: true, value: 'implicit scalar' } 
    8 - !Scalar { implicit: true, value: 'data' } 
    9 - !Scalar { implicit: true, value: 'quoted scalar' } 
     5- !Scalar { implicit: [true,true], value: 'empty scalar' } 
     6- !Scalar { implicit: [true,false], value: '' } 
     7- !Scalar { implicit: [true,true], value: 'implicit scalar' } 
     8- !Scalar { implicit: [true,true], value: 'data' } 
     9- !Scalar { implicit: [true,true], value: 'quoted scalar' } 
    1010- !Scalar { value: 'data', style: '"' } 
    11 - !Scalar { implicit: true, value: 'block scalar' } 
     11- !Scalar { implicit: [true,true], value: 'block scalar' } 
    1212- !Scalar { value: 'data', style: '|' } 
    13 - !Scalar { implicit: true, value: 'empty scalar with tag' } 
    14 - !Scalar { implicit: true, tag: '!mytag', value: '' } 
    15 - !Scalar { implicit: true, value: 'implicit scalar with tag' } 
    16 - !Scalar { implicit: true, tag: '!mytag', value: 'data' } 
    17 - !Scalar { implicit: true, value: 'quoted scalar with tag' } 
    18 - !Scalar { value: 'data', style: '"', tag: '!mytag' } 
    19 - !Scalar { implicit: true, value: 'block scalar with tag' } 
    20 - !Scalar { value: 'data', style: '|', tag: '!mytag' } 
    21 - !Scalar { implicit: true, value: 'single character' } 
    22 - !Scalar { value: 'a', implicit: true } 
    23 - !Scalar { implicit: true, value: 'single digit' } 
    24 - !Scalar { value: '1', implicit: true } 
     13- !Scalar { implicit: [true,true], value: 'empty scalar with tag' } 
     14- !Scalar { implicit: [false,false], tag: '!mytag', value: '' } 
     15- !Scalar { implicit: [true,true], value: 'implicit scalar with tag' } 
     16- !Scalar { implicit: [false,false], tag: '!mytag', value: 'data' } 
     17- !Scalar { implicit: [true,true], value: 'quoted scalar with tag' } 
     18- !Scalar { value: 'data', style: '"', tag: '!mytag', implicit: [false,false] } 
     19- !Scalar { implicit: [true,true], value: 'block scalar with tag' } 
     20- !Scalar { value: 'data', style: '|', tag: '!mytag', implicit: [false,false] } 
     21- !Scalar { implicit: [true,true], value: 'single character' } 
     22- !Scalar { value: 'a', implicit: [true,true] } 
     23- !Scalar { implicit: [true,true], value: 'single digit' } 
     24- !Scalar { value: '1', implicit: [true,false] } 
    2525- !MappingEnd 
    2626- !DocumentEnd 
  • pyyaml/trunk/tests/data/sequences.events

    r132 r137  
    77 
    88- !DocumentStart 
    9 - !SequenceStart { tag: '!mytag' } 
     9- !SequenceStart { tag: '!mytag', implicit: false } 
    1010- !SequenceEnd 
    1111- !DocumentEnd 
     
    1515- !SequenceStart 
    1616- !SequenceEnd 
    17 - !SequenceStart { tag: '!mytag' } 
     17- !SequenceStart { tag: '!mytag', implicit: false } 
    1818- !SequenceEnd 
    1919- !SequenceStart 
    2020- !Scalar 
    2121- !Scalar { value: 'data' } 
    22 - !Scalar { tag: '!mytag', value: 'data' } 
     22- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' } 
    2323- !SequenceEnd 
    2424- !SequenceStart 
     
    3030- !SequenceEnd 
    3131- !SequenceStart 
    32 - !SequenceStart { tag: '!mytag' } 
     32- !SequenceStart { tag: '!mytag', implicit: false } 
    3333- !SequenceStart 
    3434- !Scalar { value: 'data' } 
     
    4848- !SequenceEnd 
    4949- !Scalar { value: 'key2' } 
    50 - !SequenceStart { tag: '!mytag1' } 
     50- !SequenceStart { tag: '!mytag1', implicit: false } 
    5151- !Scalar { value: 'data3' } 
    5252- !SequenceStart 
     
    5454- !Scalar { value: 'data5' } 
    5555- !SequenceEnd 
    56 - !SequenceStart { tag: '!mytag2' } 
     56- !SequenceStart { tag: '!mytag2', implicit: false } 
    5757- !Scalar { value: 'data6' } 
    5858- !Scalar { value: 'data7' } 
     
    7070- !Scalar 
    7171- !Scalar { value: 'data' } 
    72 - !Scalar { tag: '!mytag', value: 'data' } 
    73 - !SequenceStart { tag: '!mytag' } 
     72- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' } 
     73- !SequenceStart { tag: '!mytag', implicit: false } 
    7474- !Scalar { value: 'data' } 
    7575- !Scalar { value: 'data' } 
  • pyyaml/trunk/tests/data/sloppy-indentation.canonical

    r117 r137  
    1616"the parser does not require scalars to be indented with at least one space" 
    1717--- !!map 
    18 { ? !!str "foo": { ? !!str "bar" : "quoted scalars may not adhere indentation" } } 
     18{ ? !!str "foo": { ? !!str "bar" : !!str "quoted scalars may not adhere indentation" } } 
  • pyyaml/trunk/tests/test_appliance.py

    r136 r137  
    263263                tag = self.get_token_value() 
    264264            if self.check_token(ScalarToken): 
    265                 self.events.append(ScalarEvent(anchor, tag, False, self.get_token_value(), None, None)) 
     265                self.events.append(ScalarEvent(anchor, tag, (False, False), self.get_token_value(), None, None)) 
    266266            elif self.check_token(FlowSequenceStartToken): 
    267267                self.events.append(SequenceStartEvent(anchor, tag, None, None)) 
     
    322322        return self.events[0] 
    323323 
    324 class CanonicalLoader(CanonicalScanner, CanonicalParser, Composer, Constructor, Detector): 
     324class CanonicalLoader(CanonicalScanner, CanonicalParser, Composer, Constructor, Resolver): 
    325325 
    326326    def __init__(self, stream): 
     
    331331        Composer.__init__(self) 
    332332        Constructor.__init__(self) 
    333         Detector.__init__(self) 
     333        Resolver.__init__(self) 
    334334 
    335335def canonical_scan(stream): 
  • pyyaml/trunk/tests/test_emitter.py

    r136 r137  
    3131            if isinstance(event, ScalarEvent): 
    3232                #self.failUnlessEqual(event.implicit, new_event.implicit) 
    33                 if not event.implicit and not new_event.implicit: 
     33                if True not in event.implicit+new_event.implicit: 
    3434                    self.failUnlessEqual(event.tag, new_event.tag) 
    3535                self.failUnlessEqual(event.value, new_event.value) 
     
    5959        if class_name in ['ScalarEvent', 'SequenceStartEvent', 'MappingStartEvent']: 
    6060            mapping.setdefault('tag', None) 
     61        if class_name in ['SequenceStartEvent', 'MappingStartEvent']: 
     62            mapping.setdefault('implicit', True) 
    6163        if class_name == 'ScalarEvent': 
    62             mapping.setdefault('implicit', False) 
     64            mapping.setdefault('implicit', (False, True)) 
    6365            mapping.setdefault('value', '') 
    6466        value = getattr(yaml, class_name)(**mapping) 
  • pyyaml/trunk/tests/test_resolver.py

    r136 r137  
    44from yaml import * 
    55 
    6 class TestDetector(test_appliance.TestAppliance): 
     6class MyLoader(Loader): 
     7    pass 
    78 
    8     def _testDetector(self, test_name, data_filename, detect_filename): 
     9class MyDumper(Dumper): 
     10    pass 
     11 
     12add_path_resolver(u'!root', [], 
     13        Loader=MyLoader, Dumper=MyDumper) 
     14 
     15add_path_resolver(u'!root/scalar', [], str, 
     16        Loader=MyLoader, Dumper=MyDumper) 
     17 
     18add_path_resolver(u'!root/key11/key12/*', ['key11', 'key12'], 
     19        Loader=MyLoader, Dumper=MyDumper) 
     20 
     21add_path_resolver(u'!root/key21/1/*', ['key21', 1], 
     22        Loader=MyLoader, Dumper=MyDumper) 
     23 
     24add_path_resolver(u'!root/key31/*/*/key14/map', ['key31', None, None, 'key14'], map, 
     25        Loader=MyLoader, Dumper=MyDumper) 
     26 
     27class TestResolver(test_appliance.TestAppliance): 
     28 
     29    def _testImplicitResolver(self, test_name, data_filename, detect_filename): 
    930        node = None 
    1031        correct_tag = None 
     
    2647            raise 
    2748 
    28 TestDetector.add_tests('testDetector', '.data', '.detect') 
     49    def _testPathResolverLoader(self, test_name, data_filename, path_filename): 
     50        #print serialize_all(compose_all(file(data_filename, 'rb').read(), Loader=MyLoader)) 
     51        nodes1 = compose_all(file(data_filename, 'rb').read(), Loader=MyLoader) 
     52        nodes2 = compose_all(file(path_filename, 'rb').read()) 
     53        for node1, node2 in zip(nodes1, nodes2): 
     54            self.failUnlessEqual(self._convert(node1), self._convert(node2)) 
    2955 
     56    def _testPathResolverDumper(self, test_name, data_filename, path_filename): 
     57        for filename in [data_filename, path_filename]: 
     58            output = serialize_all(compose_all(file(filename, 'rb').read()), Dumper=MyDumper) 
     59            #print output 
     60            nodes1 = compose_all(output) 
     61            nodes2 = compose_all(file(data_filename, 'rb').read()) 
     62            for node1, node2 in zip(nodes1, nodes2): 
     63                self.failUnlessEqual(self._convert(node1), self._convert(node2)) 
     64 
     65    def _convert(self, node): 
     66        if isinstance(node, ScalarNode): 
     67            return node.tag, node.value 
     68        elif isinstance(node, SequenceNode): 
     69            value = [] 
     70            for item in node.value: 
     71                value.append(self._convert(item)) 
     72            return node.tag, value 
     73        elif isinstance(node, MappingNode): 
     74            value = [] 
     75            for key in node.value: 
     76                item = node.value[key] 
     77                value.append((self._convert(key), self._convert(item))) 
     78            value.sort() 
     79            return node.tag, value 
     80 
     81TestResolver.add_tests('testImplicitResolver', '.data', '.detect') 
     82TestResolver.add_tests('testPathResolverLoader', '.data', '.path') 
     83TestResolver.add_tests('testPathResolverDumper', '.data', '.path') 
     84 
  • pyyaml/trunk/tests/test_yaml.py

    r133 r137  
    88from test_structure import * 
    99from test_errors import * 
    10 from test_detector import * 
     10from test_resolver import * 
    1111from test_constructor import * 
    1212from test_emitter import * 
Note: See TracChangeset for help on using the changeset viewer.