source: pyyaml/trunk/lib/yaml/constructor.py @ 269

Revision 269, 24.8 KB checked in by xi, 6 years ago (diff)

Fixed Python 2.3 compatibility (thanks to Julian Scheid for suggestion).

RevLine 
[55]1
[133]2__all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
3    'ConstructorError']
[57]4
[55]5from error import *
6from nodes import *
7
[225]8import datetime
[55]9
10try:
11    set
12except NameError:
13    from sets import Set as set
14
[235]15import binascii, re, sys, types
[55]16
17class ConstructorError(MarkedYAMLError):
18    pass
19
[222]20class BaseConstructor(object):
[55]21
[136]22    yaml_constructors = {}
23    yaml_multi_constructors = {}
24
25    def __init__(self):
[55]26        self.constructed_objects = {}
[142]27        self.recursive_objects = {}
[222]28        self.state_generators = []
29        self.deep_construct = False
[55]30
[136]31    def check_data(self):
[55]32        # If there are more documents available?
[136]33        return self.check_node()
[55]34
[136]35    def get_data(self):
[55]36        # Construct and return the next document.
[136]37        if self.check_node():
38            return self.construct_document(self.get_node())
[55]39
[258]40    def get_single_data(self):
41        # Ensure that the stream contains a single document and construct it.
42        node = self.get_single_node()
43        if node is not None:
44            return self.construct_document(node)
45        return None
46
[55]47    def construct_document(self, node):
[136]48        data = self.construct_object(node)
[222]49        while self.state_generators:
50            state_generators = self.state_generators
51            self.state_generators = []
52            for generator in state_generators:
53                for dummy in generator:
54                    pass
[55]55        self.constructed_objects = {}
[142]56        self.recursive_objects = {}
[222]57        self.deep_construct = False
[136]58        return data
[55]59
[222]60    def construct_object(self, node, deep=False):
61        if deep:
62            old_deep = self.deep_construct
63            self.deep_construct = True
[55]64        if node in self.constructed_objects:
65            return self.constructed_objects[node]
[142]66        if node in self.recursive_objects:
67            raise ConstructorError(None, None,
[222]68                    "found unconstructable recursive node", node.start_mark)
[142]69        self.recursive_objects[node] = None
[136]70        constructor = None
[222]71        state_constructor = None
72        tag_suffix = None
[55]73        if node.tag in self.yaml_constructors:
[222]74            constructor = self.yaml_constructors[node.tag]
[136]75        else:
76            for tag_prefix in self.yaml_multi_constructors:
77                if node.tag.startswith(tag_prefix):
78                    tag_suffix = node.tag[len(tag_prefix):]
[222]79                    constructor = self.yaml_multi_constructors[tag_prefix]
[139]80                    break
[136]81            else:
82                if None in self.yaml_multi_constructors:
[222]83                    tag_suffix = node.tag
84                    constructor = self.yaml_multi_constructors[None]
[136]85                elif None in self.yaml_constructors:
[222]86                    constructor = self.yaml_constructors[None]
[136]87                elif isinstance(node, ScalarNode):
[222]88                    constructor = self.__class__.construct_scalar
[136]89                elif isinstance(node, SequenceNode):
[222]90                    constructor = self.__class__.construct_sequence
[136]91                elif isinstance(node, MappingNode):
[222]92                    constructor = self.__class__.construct_mapping
93        if tag_suffix is None:
94            data = constructor(self, node)
95        else:
96            data = constructor(self, tag_suffix, node)
[235]97        if isinstance(data, types.GeneratorType):
[222]98            generator = data
99            data = generator.next()
100            if self.deep_construct:
101                for dummy in generator:
102                    pass
103            else:
104                self.state_generators.append(generator)
[136]105        self.constructed_objects[node] = data
[142]106        del self.recursive_objects[node]
[222]107        if deep:
108            self.deep_construct = old_deep
[136]109        return data
[55]110
111    def construct_scalar(self, node):
112        if not isinstance(node, ScalarNode):
113            raise ConstructorError(None, None,
114                    "expected a scalar node, but found %s" % node.id,
[116]115                    node.start_mark)
[55]116        return node.value
117
[222]118    def construct_sequence(self, node, deep=False):
[55]119        if not isinstance(node, SequenceNode):
120            raise ConstructorError(None, None,
121                    "expected a sequence node, but found %s" % node.id,
[116]122                    node.start_mark)
[222]123        return [self.construct_object(child, deep=deep)
124                for child in node.value]
[55]125
[222]126    def construct_mapping(self, node, deep=False):
[55]127        if not isinstance(node, MappingNode):
128            raise ConstructorError(None, None,
129                    "expected a mapping node, but found %s" % node.id,
[116]130                    node.start_mark)
[55]131        mapping = {}
[222]132        for key_node, value_node in node.value:
133            key = self.construct_object(key_node, deep=deep)
134            try:
135                hash(key)
136            except TypeError, exc:
137                raise ConstructorError("while constructing a mapping", node.start_mark,
138                        "found unacceptable key (%s)" % exc, key_node.start_mark)
139            value = self.construct_object(value_node, deep=deep)
140            mapping[key] = value
[55]141        return mapping
142
[222]143    def construct_pairs(self, node, deep=False):
[55]144        if not isinstance(node, MappingNode):
145            raise ConstructorError(None, None,
146                    "expected a mapping node, but found %s" % node.id,
[116]147                    node.start_mark)
[55]148        pairs = []
[222]149        for key_node, value_node in node.value:
150            key = self.construct_object(key_node, deep=deep)
151            value = self.construct_object(value_node, deep=deep)
[55]152            pairs.append((key, value))
153        return pairs
154
155    def add_constructor(cls, tag, constructor):
156        if not 'yaml_constructors' in cls.__dict__:
157            cls.yaml_constructors = cls.yaml_constructors.copy()
158        cls.yaml_constructors[tag] = constructor
159    add_constructor = classmethod(add_constructor)
160
[136]161    def add_multi_constructor(cls, tag_prefix, multi_constructor):
162        if not 'yaml_multi_constructors' in cls.__dict__:
163            cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy()
164        cls.yaml_multi_constructors[tag_prefix] = multi_constructor
165    add_multi_constructor = classmethod(add_multi_constructor)
[55]166
[133]167class SafeConstructor(BaseConstructor):
[55]168
[222]169    def construct_scalar(self, node):
170        if isinstance(node, MappingNode):
171            for key_node, value_node in node.value:
172                if key_node.tag == u'tag:yaml.org,2002:value':
173                    return self.construct_scalar(value_node)
174        return BaseConstructor.construct_scalar(self, node)
175
176    def flatten_mapping(self, node):
177        merge = []
178        index = 0
179        while index < len(node.value):
180            key_node, value_node = node.value[index]
181            if key_node.tag == u'tag:yaml.org,2002:merge':
182                del node.value[index]
183                if isinstance(value_node, MappingNode):
184                    self.flatten_mapping(value_node)
185                    merge.extend(value_node.value)
186                elif isinstance(value_node, SequenceNode):
187                    submerge = []
188                    for subnode in value_node.value:
189                        if not isinstance(subnode, MappingNode):
190                            raise ConstructorError("while constructing a mapping",
191                                    node.start_mark,
192                                    "expected a mapping for merging, but found %s"
193                                    % subnode.id, subnode.start_mark)
194                        self.flatten_mapping(subnode)
195                        submerge.append(subnode.value)
196                    submerge.reverse()
197                    for value in submerge:
198                        merge.extend(value)
199                else:
200                    raise ConstructorError("while constructing a mapping", node.start_mark,
201                            "expected a mapping or list of mappings for merging, but found %s"
202                            % value_node.id, value_node.start_mark)
203            elif key_node.tag == u'tag:yaml.org,2002:value':
204                key_node.tag = u'tag:yaml.org,2002:str'
205                index += 1
206            else:
207                index += 1
208        if merge:
209            node.value = merge + node.value
210
211    def construct_mapping(self, node, deep=False):
212        if isinstance(node, MappingNode):
213            self.flatten_mapping(node)
214        return BaseConstructor.construct_mapping(self, node, deep=deep)
215
[55]216    def construct_yaml_null(self, node):
217        self.construct_scalar(node)
218        return None
219
220    bool_values = {
221        u'yes':     True,
222        u'no':      False,
223        u'true':    True,
224        u'false':   False,
225        u'on':      True,
226        u'off':     False,
227    }
228
229    def construct_yaml_bool(self, node):
230        value = self.construct_scalar(node)
231        return self.bool_values[value.lower()]
232
233    def construct_yaml_int(self, node):
234        value = str(self.construct_scalar(node))
235        value = value.replace('_', '')
236        sign = +1
237        if value[0] == '-':
238            sign = -1
239        if value[0] in '+-':
240            value = value[1:]
241        if value == '0':
242            return 0
243        elif value.startswith('0b'):
244            return sign*int(value[2:], 2)
245        elif value.startswith('0x'):
246            return sign*int(value[2:], 16)
247        elif value[0] == '0':
248            return sign*int(value, 8)
249        elif ':' in value:
250            digits = [int(part) for part in value.split(':')]
251            digits.reverse()
252            base = 1
253            value = 0
254            for digit in digits:
255                value += digit*base
256                base *= 60
257            return sign*value
258        else:
259            return sign*int(value)
260
[168]261    inf_value = 1e300
[173]262    while inf_value != inf_value*inf_value:
[168]263        inf_value *= inf_value
[173]264    nan_value = -inf_value/inf_value   # Trying to make a quiet NaN (like C99).
[55]265
266    def construct_yaml_float(self, node):
267        value = str(self.construct_scalar(node))
[175]268        value = value.replace('_', '').lower()
[55]269        sign = +1
270        if value[0] == '-':
[58]271            sign = -1
[55]272        if value[0] in '+-':
273            value = value[1:]
[175]274        if value == '.inf':
[55]275            return sign*self.inf_value
[175]276        elif value == '.nan':
[55]277            return self.nan_value
278        elif ':' in value:
279            digits = [float(part) for part in value.split(':')]
280            digits.reverse()
281            base = 1
282            value = 0.0
283            for digit in digits:
284                value += digit*base
285                base *= 60
286            return sign*value
287        else:
[170]288            return sign*float(value)
[55]289
290    def construct_yaml_binary(self, node):
291        value = self.construct_scalar(node)
292        try:
293            return str(value).decode('base64')
294        except (binascii.Error, UnicodeEncodeError), exc:
295            raise ConstructorError(None, None,
[116]296                    "failed to decode base64 data: %s" % exc, node.start_mark) 
[55]297
[56]298    timestamp_regexp = re.compile(
299            ur'''^(?P<year>[0-9][0-9][0-9][0-9])
300                -(?P<month>[0-9][0-9]?)
301                -(?P<day>[0-9][0-9]?)
[58]302                (?:(?:[Tt]|[ \t]+)
[56]303                (?P<hour>[0-9][0-9]?)
304                :(?P<minute>[0-9][0-9])
305                :(?P<second>[0-9][0-9])
[234]306                (?:\.(?P<fraction>[0-9]*))?
[225]307                (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
308                (?::(?P<tz_minute>[0-9][0-9]))?))?)?$''', re.X)
[56]309
310    def construct_yaml_timestamp(self, node):
311        value = self.construct_scalar(node)
[58]312        match = self.timestamp_regexp.match(node.value)
[56]313        values = match.groupdict()
[225]314        year = int(values['year'])
315        month = int(values['month'])
316        day = int(values['day'])
317        if not values['hour']:
318            return datetime.date(year, month, day)
319        hour = int(values['hour'])
320        minute = int(values['minute'])
321        second = int(values['second'])
322        fraction = 0
323        if values['fraction']:
[269]324            fraction = values['fraction'][:6]
325            while len(fraction) < 6:
326                fraction += '0'
327            fraction = int(fraction)
[225]328        delta = None
329        if values['tz_sign']:
330            tz_hour = int(values['tz_hour'])
331            tz_minute = int(values['tz_minute'] or 0)
332            delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute)
333            if values['tz_sign'] == '-':
334                delta = -delta
335        data = datetime.datetime(year, month, day, hour, minute, second, fraction)
336        if delta:
337            data -= delta
338        return data
[56]339
340    def construct_yaml_omap(self, node):
341        # Note: we do not check for duplicate keys, because it's too
342        # CPU-expensive.
[222]343        omap = []
344        yield omap
[56]345        if not isinstance(node, SequenceNode):
[116]346            raise ConstructorError("while constructing an ordered map", node.start_mark,
347                    "expected a sequence, but found %s" % node.id, node.start_mark)
[56]348        for subnode in node.value:
349            if not isinstance(subnode, MappingNode):
[116]350                raise ConstructorError("while constructing an ordered map", node.start_mark,
[56]351                        "expected a mapping of length 1, but found %s" % subnode.id,
[116]352                        subnode.start_mark)
[58]353            if len(subnode.value) != 1:
[116]354                raise ConstructorError("while constructing an ordered map", node.start_mark,
[58]355                        "expected a single mapping item, but found %d items" % len(subnode.value),
[116]356                        subnode.start_mark)
[222]357            key_node, value_node = subnode.value[0]
[58]358            key = self.construct_object(key_node)
[222]359            value = self.construct_object(value_node)
[58]360            omap.append((key, value))
[56]361
362    def construct_yaml_pairs(self, node):
363        # Note: the same code as `construct_yaml_omap`.
[222]364        pairs = []
365        yield pairs
[56]366        if not isinstance(node, SequenceNode):
[116]367            raise ConstructorError("while constructing pairs", node.start_mark,
368                    "expected a sequence, but found %s" % node.id, node.start_mark)
[56]369        for subnode in node.value:
370            if not isinstance(subnode, MappingNode):
[116]371                raise ConstructorError("while constructing pairs", node.start_mark,
[56]372                        "expected a mapping of length 1, but found %s" % subnode.id,
[116]373                        subnode.start_mark)
[58]374            if len(subnode.value) != 1:
[116]375                raise ConstructorError("while constructing pairs", node.start_mark,
[58]376                        "expected a single mapping item, but found %d items" % len(subnode.value),
[116]377                        subnode.start_mark)
[222]378            key_node, value_node = subnode.value[0]
[58]379            key = self.construct_object(key_node)
[222]380            value = self.construct_object(value_node)
[58]381            pairs.append((key, value))
[56]382
383    def construct_yaml_set(self, node):
[222]384        data = set()
385        yield data
[56]386        value = self.construct_mapping(node)
[222]387        data.update(value)
[56]388
[55]389    def construct_yaml_str(self, node):
390        value = self.construct_scalar(node)
391        try:
[251]392            return value.encode('ascii')
[55]393        except UnicodeEncodeError:
394            return value
395
[56]396    def construct_yaml_seq(self, node):
[222]397        data = []
398        yield data
399        data.extend(self.construct_sequence(node))
[56]400
401    def construct_yaml_map(self, node):
[222]402        data = {}
403        yield data
404        value = self.construct_mapping(node)
405        data.update(value)
[56]406
[136]407    def construct_yaml_object(self, node, cls):
408        data = cls.__new__(cls)
[222]409        yield data
[136]410        if hasattr(data, '__setstate__'):
[222]411            state = self.construct_mapping(node, deep=True)
[139]412            data.__setstate__(state)
[136]413        else:
[222]414            state = self.construct_mapping(node)
[139]415            data.__dict__.update(state)
[136]416
[57]417    def construct_undefined(self, node):
418        raise ConstructorError(None, None,
419                "could not determine a constructor for the tag %r" % node.tag.encode('utf-8'),
[116]420                node.start_mark)
[57]421
[133]422SafeConstructor.add_constructor(
[55]423        u'tag:yaml.org,2002:null',
[133]424        SafeConstructor.construct_yaml_null)
[55]425
[133]426SafeConstructor.add_constructor(
[55]427        u'tag:yaml.org,2002:bool',
[133]428        SafeConstructor.construct_yaml_bool)
[55]429
[133]430SafeConstructor.add_constructor(
[55]431        u'tag:yaml.org,2002:int',
[133]432        SafeConstructor.construct_yaml_int)
[55]433
[133]434SafeConstructor.add_constructor(
[55]435        u'tag:yaml.org,2002:float',
[133]436        SafeConstructor.construct_yaml_float)
[55]437
[133]438SafeConstructor.add_constructor(
[58]439        u'tag:yaml.org,2002:binary',
[133]440        SafeConstructor.construct_yaml_binary)
[56]441
[225]442SafeConstructor.add_constructor(
443        u'tag:yaml.org,2002:timestamp',
444        SafeConstructor.construct_yaml_timestamp)
[58]445
[133]446SafeConstructor.add_constructor(
[56]447        u'tag:yaml.org,2002:omap',
[133]448        SafeConstructor.construct_yaml_omap)
[56]449
[133]450SafeConstructor.add_constructor(
[56]451        u'tag:yaml.org,2002:pairs',
[133]452        SafeConstructor.construct_yaml_pairs)
[56]453
[133]454SafeConstructor.add_constructor(
[56]455        u'tag:yaml.org,2002:set',
[133]456        SafeConstructor.construct_yaml_set)
[56]457
[133]458SafeConstructor.add_constructor(
[55]459        u'tag:yaml.org,2002:str',
[133]460        SafeConstructor.construct_yaml_str)
[55]461
[133]462SafeConstructor.add_constructor(
[56]463        u'tag:yaml.org,2002:seq',
[133]464        SafeConstructor.construct_yaml_seq)
[56]465
[133]466SafeConstructor.add_constructor(
[56]467        u'tag:yaml.org,2002:map',
[133]468        SafeConstructor.construct_yaml_map)
[56]469
[133]470SafeConstructor.add_constructor(None,
471        SafeConstructor.construct_undefined)
[57]472
[133]473class Constructor(SafeConstructor):
[55]474
[139]475    def construct_python_str(self, node):
476        return self.construct_scalar(node).encode('utf-8')
477
478    def construct_python_unicode(self, node):
479        return self.construct_scalar(node)
480
481    def construct_python_long(self, node):
482        return long(self.construct_yaml_int(node))
483
484    def construct_python_complex(self, node):
485       return complex(self.construct_scalar(node))
486
487    def construct_python_tuple(self, node):
[222]488        return tuple(self.construct_sequence(node))
[139]489
490    def find_python_module(self, name, mark):
491        if not name:
492            raise ConstructorError("while constructing a Python module", mark,
493                    "expected non-empty name appended to the tag", mark)
494        try:
495            __import__(name)
496        except ImportError, exc:
497            raise ConstructorError("while constructing a Python module", mark,
498                    "cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark)
499        return sys.modules[name]
500
501    def find_python_name(self, name, mark):
502        if not name:
503            raise ConstructorError("while constructing a Python object", mark,
504                    "expected non-empty name appended to the tag", mark)
505        if u'.' in name:
[146]506            # Python 2.4 only
507            #module_name, object_name = name.rsplit('.', 1)
508            items = name.split('.')
509            object_name = items.pop()
510            module_name = '.'.join(items)
[139]511        else:
512            module_name = '__builtin__'
513            object_name = name
514        try:
515            __import__(module_name)
516        except ImportError, exc:
517            raise ConstructorError("while constructing a Python object", mark,
518                    "cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark)
519        module = sys.modules[module_name]
520        if not hasattr(module, object_name):
521            raise ConstructorError("while constructing a Python object", mark,
522                    "cannot find %r in the module %r" % (object_name.encode('utf-8'),
523                        module.__name__), mark)
524        return getattr(module, object_name)
525
526    def construct_python_name(self, suffix, node):
527        value = self.construct_scalar(node)
528        if value:
529            raise ConstructorError("while constructing a Python name", node.start_mark,
530                    "expected the empty value, but found %r" % value.encode('utf-8'),
531                    node.start_mark)
532        return self.find_python_name(suffix, node.start_mark)
533
534    def construct_python_module(self, suffix, node):
535        value = self.construct_scalar(node)
536        if value:
537            raise ConstructorError("while constructing a Python module", node.start_mark,
538                    "expected the empty value, but found %r" % value.encode('utf-8'),
539                    node.start_mark)
540        return self.find_python_module(suffix, node.start_mark)
541
[147]542    class classobj: pass
543
544    def make_python_instance(self, suffix, node,
545            args=None, kwds=None, newobj=False):
546        if not args:
547            args = []
548        if not kwds:
549            kwds = {}
550        cls = self.find_python_name(suffix, node.start_mark)
551        if newobj and isinstance(cls, type(self.classobj))  \
552                and not args and not kwds:
553            instance = self.classobj()
554            instance.__class__ = cls
555            return instance
556        elif newobj and isinstance(cls, type):
557            return cls.__new__(cls, *args, **kwds)
558        else:
559            return cls(*args, **kwds)
560
561    def set_python_instance_state(self, instance, state):
562        if hasattr(instance, '__setstate__'):
563            instance.__setstate__(state)
564        else:
565            slotstate = {}
566            if isinstance(state, tuple) and len(state) == 2:
567                state, slotstate = state
568            if hasattr(instance, '__dict__'):
569                instance.__dict__.update(state)
570            elif state:
571                slotstate.update(state)
572            for key, value in slotstate.items():
573                setattr(object, key, value)
574
575    def construct_python_object(self, suffix, node):
576        # Format:
577        #   !!python/object:module.name { ... state ... }
578        instance = self.make_python_instance(suffix, node, newobj=True)
[222]579        yield instance
580        deep = hasattr(instance, '__setstate__')
581        state = self.construct_mapping(node, deep=deep)
[147]582        self.set_python_instance_state(instance, state)
583
584    def construct_python_object_apply(self, suffix, node, newobj=False):
585        # Format:
586        #   !!python/object/apply       # (or !!python/object/new)
587        #   args: [ ... arguments ... ]
588        #   kwds: { ... keywords ... }
589        #   state: ... state ...
590        #   listitems: [ ... listitems ... ]
591        #   dictitems: { ... dictitems ... }
592        # or short format:
593        #   !!python/object/apply [ ... arguments ... ]
594        # The difference between !!python/object/apply and !!python/object/new
595        # is how an object is created, check make_python_instance for details.
596        if isinstance(node, SequenceNode):
[222]597            args = self.construct_sequence(node, deep=True)
[147]598            kwds = {}
599            state = {}
600            listitems = []
601            dictitems = {}
602        else:
[222]603            value = self.construct_mapping(node, deep=True)
[147]604            args = value.get('args', [])
605            kwds = value.get('kwds', {})
606            state = value.get('state', {})
607            listitems = value.get('listitems', [])
608            dictitems = value.get('dictitems', {})
609        instance = self.make_python_instance(suffix, node, args, kwds, newobj)
610        if state:
611            self.set_python_instance_state(instance, state)
612        if listitems:
613            instance.extend(listitems)
614        if dictitems:
615            for key in dictitems:
616                instance[key] = dictitems[key]
617        return instance
618
619    def construct_python_object_new(self, suffix, node):
620        return self.construct_python_object_apply(suffix, node, newobj=True)
621
[139]622Constructor.add_constructor(
623    u'tag:yaml.org,2002:python/none',
624    Constructor.construct_yaml_null)
625
626Constructor.add_constructor(
627    u'tag:yaml.org,2002:python/bool',
628    Constructor.construct_yaml_bool)
629
630Constructor.add_constructor(
631    u'tag:yaml.org,2002:python/str',
632    Constructor.construct_python_str)
633
634Constructor.add_constructor(
635    u'tag:yaml.org,2002:python/unicode',
636    Constructor.construct_python_unicode)
637
638Constructor.add_constructor(
639    u'tag:yaml.org,2002:python/int',
640    Constructor.construct_yaml_int)
641
642Constructor.add_constructor(
643    u'tag:yaml.org,2002:python/long',
644    Constructor.construct_python_long)
645
646Constructor.add_constructor(
647    u'tag:yaml.org,2002:python/float',
648    Constructor.construct_yaml_float)
649
650Constructor.add_constructor(
651    u'tag:yaml.org,2002:python/complex',
652    Constructor.construct_python_complex)
653
654Constructor.add_constructor(
655    u'tag:yaml.org,2002:python/list',
656    Constructor.construct_yaml_seq)
657
658Constructor.add_constructor(
659    u'tag:yaml.org,2002:python/tuple',
660    Constructor.construct_python_tuple)
661
662Constructor.add_constructor(
663    u'tag:yaml.org,2002:python/dict',
664    Constructor.construct_yaml_map)
665
666Constructor.add_multi_constructor(
667    u'tag:yaml.org,2002:python/name:',
668    Constructor.construct_python_name)
669
670Constructor.add_multi_constructor(
671    u'tag:yaml.org,2002:python/module:',
672    Constructor.construct_python_module)
673
[147]674Constructor.add_multi_constructor(
675    u'tag:yaml.org,2002:python/object:',
676    Constructor.construct_python_object)
677
678Constructor.add_multi_constructor(
679    u'tag:yaml.org,2002:python/object/apply:',
680    Constructor.construct_python_object_apply)
681
682Constructor.add_multi_constructor(
683    u'tag:yaml.org,2002:python/object/new:',
684    Constructor.construct_python_object_new)
685
Note: See TracBrowser for help on using the repository browser.