source: pyyaml/trunk/lib3/yaml/constructor.py @ 328

Revision 328, 24.7 KB checked in by xi, 6 years ago (diff)

Added basic support for Python 3 (Thanks idadesub(at)users(dot)sourceforge(dot)net).

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