__all__=['BaseConstructor','SafeConstructor','Constructor','ConstructorError']from.errorimport*from.nodesimport*importcollections,datetime,base64,binascii,re,sys,typesclassConstructorError(MarkedYAMLError):passclassBaseConstructor:yaml_constructors={}yaml_multi_constructors={}def__init__(self):self.constructed_objects={}self.recursive_objects={}self.state_generators=[]self.deep_construct=Falsedefcheck_data(self):# If there are more documents available?returnself.check_node()defget_data(self):# Construct and return the next document.ifself.check_node():returnself.construct_document(self.get_node())defget_single_data(self):# Ensure that the stream contains a single document and construct it.node=self.get_single_node()ifnodeisnotNone:returnself.construct_document(node)returnNonedefconstruct_document(self,node):data=self.construct_object(node)whileself.state_generators:state_generators=self.state_generatorsself.state_generators=[]forgeneratorinstate_generators:fordummyingenerator:passself.constructed_objects={}self.recursive_objects={}self.deep_construct=Falsereturndatadefconstruct_object(self,node,deep=False):ifnodeinself.constructed_objects:returnself.constructed_objects[node]ifdeep:old_deep=self.deep_constructself.deep_construct=Trueifnodeinself.recursive_objects:raiseConstructorError(None,None,"found unconstructable recursive node",node.start_mark)self.recursive_objects[node]=Noneconstructor=Nonetag_suffix=Noneifnode.taginself.yaml_constructors:constructor=self.yaml_constructors[node.tag]else:fortag_prefixinself.yaml_multi_constructors:ifnode.tag.startswith(tag_prefix):tag_suffix=node.tag[len(tag_prefix):]constructor=self.yaml_multi_constructors[tag_prefix]breakelse:ifNoneinself.yaml_multi_constructors:tag_suffix=node.tagconstructor=self.yaml_multi_constructors[None]elifNoneinself.yaml_constructors:constructor=self.yaml_constructors[None]elifisinstance(node,ScalarNode):constructor=self.__class__.construct_scalarelifisinstance(node,SequenceNode):constructor=self.__class__.construct_sequenceelifisinstance(node,MappingNode):constructor=self.__class__.construct_mappingiftag_suffixisNone:data=constructor(self,node)else:data=constructor(self,tag_suffix,node)ifisinstance(data,types.GeneratorType):generator=datadata=next(generator)ifself.deep_construct:fordummyingenerator:passelse:self.state_generators.append(generator)self.constructed_objects[node]=datadelself.recursive_objects[node]ifdeep:self.deep_construct=old_deepreturndatadefconstruct_scalar(self,node):ifnotisinstance(node,ScalarNode):raiseConstructorError(None,None,"expected a scalar node, but found %s"%node.id,node.start_mark)returnnode.valuedefconstruct_sequence(self,node,deep=False):ifnotisinstance(node,SequenceNode):raiseConstructorError(None,None,"expected a sequence node, but found %s"%node.id,node.start_mark)return[self.construct_object(child,deep=deep)forchildinnode.value]defconstruct_mapping(self,node,deep=False):ifnotisinstance(node,MappingNode):raiseConstructorError(None,None,"expected a mapping node, but found %s"%node.id,node.start_mark)mapping={}forkey_node,value_nodeinnode.value:key=self.construct_object(key_node,deep=deep)ifnotisinstance(key,collections.Hashable):raiseConstructorError("while constructing a mapping",node.start_mark,"found unhashable key",key_node.start_mark)value=self.construct_object(value_node,deep=deep)mapping[key]=valuereturnmappingdefconstruct_pairs(self,node,deep=False):ifnotisinstance(node,MappingNode):raiseConstructorError(None,None,"expected a mapping node, but found %s"%node.id,node.start_mark)pairs=[]forkey_node,value_nodeinnode.value:key=self.construct_object(key_node,deep=deep)value=self.construct_object(value_node,deep=deep)pairs.append((key,value))returnpairs@classmethoddefadd_constructor(cls,tag,constructor):ifnot'yaml_constructors'incls.__dict__:cls.yaml_constructors=cls.yaml_constructors.copy()cls.yaml_constructors[tag]=constructor@classmethoddefadd_multi_constructor(cls,tag_prefix,multi_constructor):ifnot'yaml_multi_constructors'incls.__dict__:cls.yaml_multi_constructors=cls.yaml_multi_constructors.copy()cls.yaml_multi_constructors[tag_prefix]=multi_constructorclassSafeConstructor(BaseConstructor):defconstruct_scalar(self,node):ifisinstance(node,MappingNode):forkey_node,value_nodeinnode.value:ifkey_node.tag=='tag:yaml.org,2002:value':returnself.construct_scalar(value_node)returnsuper().construct_scalar(node)defflatten_mapping(self,node):merge=[]index=0whileindex<len(node.value):key_node,value_node=node.value[index]ifkey_node.tag=='tag:yaml.org,2002:merge':delnode.value[index]ifisinstance(value_node,MappingNode):self.flatten_mapping(value_node)merge.extend(value_node.value)elifisinstance(value_node,SequenceNode):submerge=[]forsubnodeinvalue_node.value:ifnotisinstance(subnode,MappingNode):raiseConstructorError("while constructing a mapping",node.start_mark,"expected a mapping for merging, but found %s"%subnode.id,subnode.start_mark)self.flatten_mapping(subnode)submerge.append(subnode.value)submerge.reverse()forvalueinsubmerge:merge.extend(value)else:raiseConstructorError("while constructing a mapping",node.start_mark,"expected a mapping or list of mappings for merging, but found %s"%value_node.id,value_node.start_mark)elifkey_node.tag=='tag:yaml.org,2002:value':key_node.tag='tag:yaml.org,2002:str'index+=1else:index+=1ifmerge:node.value=merge+node.valuedefconstruct_mapping(self,node,deep=False):ifisinstance(node,MappingNode):self.flatten_mapping(node)returnsuper().construct_mapping(node,deep=deep)defconstruct_yaml_null(self,node):self.construct_scalar(node)returnNonebool_values={'yes':True,'no':False,'true':True,'false':False,'on':True,'off':False,}defconstruct_yaml_bool(self,node):value=self.construct_scalar(node)returnself.bool_values[value.lower()]defconstruct_yaml_int(self,node):value=self.construct_scalar(node)value=value.replace('_','')sign=+1ifvalue[0]=='-':sign=-1ifvalue[0]in'+-':value=value[1:]ifvalue=='0':return0elifvalue.startswith('0b'):returnsign*int(value[2:],2)elifvalue.startswith('0x'):returnsign*int(value[2:],16)elifvalue[0]=='0':returnsign*int(value,8)elif':'invalue:digits=[int(part)forpartinvalue.split(':')]digits.reverse()base=1value=0fordigitindigits:value+=digit*basebase*=60returnsign*valueelse:returnsign*int(value)inf_value=1e300whileinf_value!=inf_value*inf_value:inf_value*=inf_valuenan_value=-inf_value/inf_value# Trying to make a quiet NaN (like C99).defconstruct_yaml_float(self,node):value=self.construct_scalar(node)value=value.replace('_','').lower()sign=+1ifvalue[0]=='-':sign=-1ifvalue[0]in'+-':value=value[1:]ifvalue=='.inf':returnsign*self.inf_valueelifvalue=='.nan':returnself.nan_valueelif':'invalue:digits=[float(part)forpartinvalue.split(':')]digits.reverse()base=1value=0.0fordigitindigits:value+=digit*basebase*=60returnsign*valueelse:returnsign*float(value)defconstruct_yaml_binary(self,node):try:value=self.construct_scalar(node).encode('ascii')exceptUnicodeEncodeErrorasexc:raiseConstructorError(None,None,"failed to convert base64 data into ascii: %s"%exc,node.start_mark)try:ifhasattr(base64,'decodebytes'):returnbase64.decodebytes(value)else:returnbase64.decodestring(value)exceptbinascii.Errorasexc:raiseConstructorError(None,None,"failed to decode base64 data: %s"%exc,node.start_mark)timestamp_regexp=re.compile(r'''^(?P<year>[0-9][0-9][0-9][0-9]) -(?P<month>[0-9][0-9]?) -(?P<day>[0-9][0-9]?) (?:(?:[Tt]|[ \t]+) (?P<hour>[0-9][0-9]?) :(?P<minute>[0-9][0-9]) :(?P<second>[0-9][0-9]) (?:\.(?P<fraction>[0-9]*))? (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?) (?::(?P<tz_minute>[0-9][0-9]))?))?)?$''',re.X)defconstruct_yaml_timestamp(self,node):value=self.construct_scalar(node)match=self.timestamp_regexp.match(node.value)values=match.groupdict()year=int(values['year'])month=int(values['month'])day=int(values['day'])ifnotvalues['hour']:returndatetime.date(year,month,day)hour=int(values['hour'])minute=int(values['minute'])second=int(values['second'])fraction=0ifvalues['fraction']:fraction=values['fraction'][:6]whilelen(fraction)<6:fraction+='0'fraction=int(fraction)delta=Noneifvalues['tz_sign']:tz_hour=int(values['tz_hour'])tz_minute=int(values['tz_minute']or0)delta=datetime.timedelta(hours=tz_hour,minutes=tz_minute)ifvalues['tz_sign']=='-':delta=-deltadata=datetime.datetime(year,month,day,hour,minute,second,fraction)ifdelta:data-=deltareturndatadefconstruct_yaml_omap(self,node):# Note: we do not check for duplicate keys, because it's too# CPU-expensive.omap=[]yieldomapifnotisinstance(node,SequenceNode):raiseConstructorError("while constructing an ordered map",node.start_mark,"expected a sequence, but found %s"%node.id,node.start_mark)forsubnodeinnode.value:ifnotisinstance(subnode,MappingNode):raiseConstructorError("while constructing an ordered map",node.start_mark,"expected a mapping of length 1, but found %s"%subnode.id,subnode.start_mark)iflen(subnode.value)!=1:raiseConstructorError("while constructing an ordered map",node.start_mark,"expected a single mapping item, but found %d items"%len(subnode.value),subnode.start_mark)key_node,value_node=subnode.value[0]key=self.construct_object(key_node)value=self.construct_object(value_node)omap.append((key,value))defconstruct_yaml_pairs(self,node):# Note: the same code as `construct_yaml_omap`.pairs=[]yieldpairsifnotisinstance(node,SequenceNode):raiseConstructorError("while constructing pairs",node.start_mark,"expected a sequence, but found %s"%node.id,node.start_mark)forsubnodeinnode.value:ifnotisinstance(subnode,MappingNode):raiseConstructorError("while constructing pairs",node.start_mark,"expected a mapping of length 1, but found %s"%subnode.id,subnode.start_mark)iflen(subnode.value)!=1:raiseConstructorError("while constructing pairs",node.start_mark,"expected a single mapping item, but found %d items"%len(subnode.value),subnode.start_mark)key_node,value_node=subnode.value[0]key=self.construct_object(key_node)value=self.construct_object(value_node)pairs.append((key,value))defconstruct_yaml_set(self,node):data=set()yielddatavalue=self.construct_mapping(node)data.update(value)defconstruct_yaml_str(self,node):returnself.construct_scalar(node)defconstruct_yaml_seq(self,node):data=[]yielddatadata.extend(self.construct_sequence(node))defconstruct_yaml_map(self,node):data={}yielddatavalue=self.construct_mapping(node)data.update(value)defconstruct_yaml_object(self,node,cls):data=cls.__new__(cls)yielddataifhasattr(data,'__setstate__'):state=self.construct_mapping(node,deep=True)data.__setstate__(state)else:state=self.construct_mapping(node)data.__dict__.update(state)defconstruct_undefined(self,node):raiseConstructorError(None,None,"could not determine a constructor for the tag %r"%node.tag,node.start_mark)SafeConstructor.add_constructor('tag:yaml.org,2002:null',SafeConstructor.construct_yaml_null)SafeConstructor.add_constructor('tag:yaml.org,2002:bool',SafeConstructor.construct_yaml_bool)SafeConstructor.add_constructor('tag:yaml.org,2002:int',SafeConstructor.construct_yaml_int)SafeConstructor.add_constructor('tag:yaml.org,2002:float',SafeConstructor.construct_yaml_float)SafeConstructor.add_constructor('tag:yaml.org,2002:binary',SafeConstructor.construct_yaml_binary)SafeConstructor.add_constructor('tag:yaml.org,2002:timestamp',SafeConstructor.construct_yaml_timestamp)SafeConstructor.add_constructor('tag:yaml.org,2002:omap',SafeConstructor.construct_yaml_omap)SafeConstructor.add_constructor('tag:yaml.org,2002:pairs',SafeConstructor.construct_yaml_pairs)SafeConstructor.add_constructor('tag:yaml.org,2002:set',SafeConstructor.construct_yaml_set)SafeConstructor.add_constructor('tag:yaml.org,2002:str',SafeConstructor.construct_yaml_str)SafeConstructor.add_constructor('tag:yaml.org,2002:seq',SafeConstructor.construct_yaml_seq)SafeConstructor.add_constructor('tag:yaml.org,2002:map',SafeConstructor.construct_yaml_map)SafeConstructor.add_constructor(None,SafeConstructor.construct_undefined)classConstructor(SafeConstructor):defconstruct_python_str(self,node):returnself.construct_scalar(node)defconstruct_python_unicode(self,node):returnself.construct_scalar(node)defconstruct_python_bytes(self,node):try:value=self.construct_scalar(node).encode('ascii')exceptUnicodeEncodeErrorasexc:raiseConstructorError(None,None,"failed to convert base64 data into ascii: %s"%exc,node.start_mark)try:ifhasattr(base64,'decodebytes'):returnbase64.decodebytes(value)else:returnbase64.decodestring(value)exceptbinascii.Errorasexc:raiseConstructorError(None,None,"failed to decode base64 data: %s"%exc,node.start_mark)defconstruct_python_long(self,node):returnself.construct_yaml_int(node)defconstruct_python_complex(self,node):returncomplex(self.construct_scalar(node))defconstruct_python_tuple(self,node):returntuple(self.construct_sequence(node))deffind_python_module(self,name,mark):ifnotname:raiseConstructorError("while constructing a Python module",mark,"expected non-empty name appended to the tag",mark)try:__import__(name)exceptImportErrorasexc:raiseConstructorError("while constructing a Python module",mark,"cannot find module %r (%s)"%(name,exc),mark)returnsys.modules[name]deffind_python_name(self,name,mark):ifnotname:raiseConstructorError("while constructing a Python object",mark,"expected non-empty name appended to the tag",mark)if'.'inname:module_name,object_name=name.rsplit('.',1)else:module_name='builtins'object_name=nametry:__import__(module_name)exceptImportErrorasexc:raiseConstructorError("while constructing a Python object",mark,"cannot find module %r (%s)"%(module_name,exc),mark)module=sys.modules[module_name]ifnothasattr(module,object_name):raiseConstructorError("while constructing a Python object",mark,"cannot find %r in the module %r"%(object_name,module.__name__),mark)returngetattr(module,object_name)defconstruct_python_name(self,suffix,node):value=self.construct_scalar(node)ifvalue:raiseConstructorError("while constructing a Python name",node.start_mark,"expected the empty value, but found %r"%value,node.start_mark)returnself.find_python_name(suffix,node.start_mark)defconstruct_python_module(self,suffix,node):value=self.construct_scalar(node)ifvalue:raiseConstructorError("while constructing a Python module",node.start_mark,"expected the empty value, but found %r"%value,node.start_mark)returnself.find_python_module(suffix,node.start_mark)defmake_python_instance(self,suffix,node,args=None,kwds=None,newobj=False):ifnotargs:args=[]ifnotkwds:kwds={}cls=self.find_python_name(suffix,node.start_mark)ifnewobjandisinstance(cls,type):returncls.__new__(cls,*args,**kwds)else:returncls(*args,**kwds)defset_python_instance_state(self,instance,state):ifhasattr(instance,'__setstate__'):instance.__setstate__(state)else:slotstate={}ifisinstance(state,tuple)andlen(state)==2:state,slotstate=stateifhasattr(instance,'__dict__'):instance.__dict__.update(state)elifstate:slotstate.update(state)forkey,valueinslotstate.items():setattr(object,key,value)defconstruct_python_object(self,suffix,node):# Format:# !!python/object:module.name { ... state ... }instance=self.make_python_instance(suffix,node,newobj=True)yieldinstancedeep=hasattr(instance,'__setstate__')state=self.construct_mapping(node,deep=deep)self.set_python_instance_state(instance,state)defconstruct_python_object_apply(self,suffix,node,newobj=False):# Format:# !!python/object/apply # (or !!python/object/new)# args: [ ... arguments ... ]# kwds: { ... keywords ... }# state: ... state ...# listitems: [ ... listitems ... ]# dictitems: { ... dictitems ... }# or short format:# !!python/object/apply [ ... arguments ... ]# The difference between !!python/object/apply and !!python/object/new# is how an object is created, check make_python_instance for details.ifisinstance(node,SequenceNode):args=self.construct_sequence(node,deep=True)kwds={}state={}listitems=[]dictitems={}else:value=self.construct_mapping(node,deep=True)args=value.get('args',[])kwds=value.get('kwds',{})state=value.get('state',{})listitems=value.get('listitems',[])dictitems=value.get('dictitems',{})instance=self.make_python_instance(suffix,node,args,kwds,newobj)ifstate:self.set_python_instance_state(instance,state)iflistitems:instance.extend(listitems)ifdictitems:forkeyindictitems:instance[key]=dictitems[key]returninstancedefconstruct_python_object_new(self,suffix,node):returnself.construct_python_object_apply(suffix,node,newobj=True)Constructor.add_constructor('tag:yaml.org,2002:python/none',Constructor.construct_yaml_null)Constructor.add_constructor('tag:yaml.org,2002:python/bool',Constructor.construct_yaml_bool)Constructor.add_constructor('tag:yaml.org,2002:python/str',Constructor.construct_python_str)Constructor.add_constructor('tag:yaml.org,2002:python/unicode',Constructor.construct_python_unicode)Constructor.add_constructor('tag:yaml.org,2002:python/bytes',Constructor.construct_python_bytes)Constructor.add_constructor('tag:yaml.org,2002:python/int',Constructor.construct_yaml_int)Constructor.add_constructor('tag:yaml.org,2002:python/long',Constructor.construct_python_long)Constructor.add_constructor('tag:yaml.org,2002:python/float',Constructor.construct_yaml_float)Constructor.add_constructor('tag:yaml.org,2002:python/complex',Constructor.construct_python_complex)Constructor.add_constructor('tag:yaml.org,2002:python/list',Constructor.construct_yaml_seq)Constructor.add_constructor('tag:yaml.org,2002:python/tuple',Constructor.construct_python_tuple)Constructor.add_constructor('tag:yaml.org,2002:python/dict',Constructor.construct_yaml_map)Constructor.add_multi_constructor('tag:yaml.org,2002:python/name:',Constructor.construct_python_name)Constructor.add_multi_constructor('tag:yaml.org,2002:python/module:',Constructor.construct_python_module)Constructor.add_multi_constructor('tag:yaml.org,2002:python/object:',Constructor.construct_python_object)Constructor.add_multi_constructor('tag:yaml.org,2002:python/object/apply:',Constructor.construct_python_object_apply)Constructor.add_multi_constructor('tag:yaml.org,2002:python/object/new:',Constructor.construct_python_object_new)