# Emitter expects events obeying the following grammar:# stream ::= STREAM-START document* STREAM-END# document ::= DOCUMENT-START node DOCUMENT-END# node ::= SCALAR | sequence | mapping# sequence ::= SEQUENCE-START node* SEQUENCE-END# mapping ::= MAPPING-START (node node)* MAPPING-END__all__=['Emitter','EmitterError']fromerrorimportYAMLErrorfromeventsimport*importreclassEmitterError(YAMLError):passclassScalarAnalysis:def__init__(self,scalar,empty,multiline,allow_flow_plain,allow_block_plain,allow_single_quoted,allow_double_quoted,allow_block):self.scalar=scalarself.empty=emptyself.multiline=multilineself.allow_flow_plain=allow_flow_plainself.allow_block_plain=allow_block_plainself.allow_single_quoted=allow_single_quotedself.allow_double_quoted=allow_double_quotedself.allow_block=allow_blockclassEmitter:DEFAULT_TAG_PREFIXES={u'!':u'!',u'tag:yaml.org,2002:':u'!!',}def__init__(self,stream,canonical=None,indent=None,width=None,allow_unicode=None,line_break=None):# The stream should have the methods `write` and possibly `flush`.self.stream=stream# Encoding can be overriden by STREAM-START.self.encoding=None# Emitter is a state machine with a stack of states to handle nested# structures.self.states=[]self.state=self.expect_stream_start# Current event and the event queue.self.events=[]self.event=None# The current indentation level and the stack of previous indents.self.indents=[]self.indent=None# Flow level.self.flow_level=0# Contexts.self.root_context=Falseself.sequence_context=Falseself.mapping_context=Falseself.simple_key_context=False# Characteristics of the last emitted character:# - current position.# - is it a whitespace?# - is it an indention character# (indentation space, '-', '?', or ':')?self.line=0self.column=0self.whitespace=Trueself.indention=True# Formatting details.self.canonical=canonicalself.allow_unicode=allow_unicodeself.best_indent=2ifindentand1<indent<10:self.best_indent=indentself.best_width=80ifwidthandwidth>self.best_indent*2:self.best_width=widthself.best_line_break=u'\n'ifline_breakin[u'\r',u'\n',u'\r\n']:self.best_line_break=line_break# Tag prefixes.self.tag_prefixes=None# Prepared anchor and tag.self.prepared_anchor=Noneself.prepared_tag=None# Scalar analysis and style.self.analysis=Noneself.style=Nonedefemit(self,event):self.events.append(event)whilenotself.need_more_events():self.event=self.events.pop(0)self.state()self.event=None# In some cases, we wait for a few next events before emitting.defneed_more_events(self):ifnotself.events:returnTrueevent=self.events[0]ifisinstance(event,DocumentStartEvent):returnself.need_events(1)elifisinstance(event,SequenceStartEvent):returnself.need_events(2)elifisinstance(event,MappingStartEvent):returnself.need_events(3)else:returnFalsedefneed_events(self,count):level=0foreventinself.events[1:]:ifisinstance(event,(DocumentStartEvent,CollectionStartEvent)):level+=1elifisinstance(event,(DocumentEndEvent,CollectionEndEvent)):level-=1elifisinstance(event,StreamEndEvent):level=-1iflevel<0:returnFalsereturn(len(self.events)<count+1)defincrease_indent(self,flow=False,indentless=False):self.indents.append(self.indent)ifself.indentisNone:ifflow:self.indent=self.best_indentelse:self.indent=0elifnotindentless:self.indent+=self.best_indent# States.# Stream handlers.defexpect_stream_start(self):ifisinstance(self.event,StreamStartEvent):ifself.event.encoding:self.encoding=self.event.encodingself.write_stream_start()self.state=self.expect_first_document_startelse:raiseEmitterError("expected StreamStartEvent, but got %s"%self.event)defexpect_nothing(self):raiseEmitterError("expected nothing, but got %s"%self.event)# Document handlers.defexpect_first_document_start(self):returnself.expect_document_start(first=True)defexpect_document_start(self,first=False):ifisinstance(self.event,DocumentStartEvent):ifself.event.version:version_text=self.prepare_version(self.event.version)self.write_version_directive(version_text)self.tag_prefixes=self.DEFAULT_TAG_PREFIXES.copy()ifself.event.tags:handles=self.event.tags.keys()handles.sort()forhandleinhandles:prefix=self.event.tags[handle]self.tag_prefixes[prefix]=handlehandle_text=self.prepare_tag_handle(handle)prefix_text=self.prepare_tag_prefix(prefix)self.write_tag_directive(handle_text,prefix_text)implicit=(firstandnotself.event.explicitandnotself.canonicalandnotself.event.versionandnotself.event.tagsandnotself.check_empty_document())ifnotimplicit:self.write_indent()self.write_indicator(u'---',True)ifself.canonical:self.write_indent()self.state=self.expect_document_rootelifisinstance(self.event,StreamEndEvent):self.write_stream_end()self.state=self.expect_nothingelse:raiseEmitterError("expected DocumentStartEvent, but got %s"%self.event)defexpect_document_end(self):ifisinstance(self.event,DocumentEndEvent):self.write_indent()ifself.event.explicit:self.write_indicator(u'...',True)self.write_indent()self.flush_stream()self.state=self.expect_document_startelse:raiseEmitterError("expected DocumentEndEvent, but got %s"%self.event)defexpect_document_root(self):self.states.append(self.expect_document_end)self.expect_node(root=True)# Node handlers.defexpect_node(self,root=False,sequence=False,mapping=False,simple_key=False):self.root_context=rootself.sequence_context=sequenceself.mapping_context=mappingself.simple_key_context=simple_keyifisinstance(self.event,AliasEvent):self.expect_alias()elifisinstance(self.event,(ScalarEvent,CollectionStartEvent)):self.process_anchor(u'&')self.process_tag()ifisinstance(self.event,ScalarEvent):self.expect_scalar()elifisinstance(self.event,SequenceStartEvent):ifself.flow_levelorself.canonicalorself.event.flow_style \
orself.check_empty_sequence():self.expect_flow_sequence()else:self.expect_block_sequence()elifisinstance(self.event,MappingStartEvent):ifself.flow_levelorself.canonicalorself.event.flow_style \
orself.check_empty_mapping():self.expect_flow_mapping()else:self.expect_block_mapping()else:raiseEmitterError("expected NodeEvent, but got %s"%self.event)defexpect_alias(self):ifself.event.anchorisNone:raiseEmitterError("anchor is not specified for alias")self.process_anchor(u'*')self.state=self.states.pop()defexpect_scalar(self):self.increase_indent(flow=True)self.process_scalar()self.indent=self.indents.pop()self.state=self.states.pop()# Flow sequence handlers.defexpect_flow_sequence(self):self.write_indicator(u'[',True,whitespace=True)self.flow_level+=1self.increase_indent(flow=True)self.state=self.expect_first_flow_sequence_itemdefexpect_first_flow_sequence_item(self):ifisinstance(self.event,SequenceEndEvent):self.indent=self.indents.pop()self.flow_level-=1self.write_indicator(u']',False)self.state=self.states.pop()else:ifself.canonicalorself.column>self.best_width:self.write_indent()self.states.append(self.expect_flow_sequence_item)self.expect_node(sequence=True)defexpect_flow_sequence_item(self):ifisinstance(self.event,SequenceEndEvent):self.indent=self.indents.pop()self.flow_level-=1ifself.canonical:self.write_indicator(u',',False)self.write_indent()self.write_indicator(u']',False)self.state=self.states.pop()else:self.write_indicator(u',',False)ifself.canonicalorself.column>self.best_width:self.write_indent()self.states.append(self.expect_flow_sequence_item)self.expect_node(sequence=True)# Flow mapping handlers.defexpect_flow_mapping(self):self.write_indicator(u'{',True,whitespace=True)self.flow_level+=1self.increase_indent(flow=True)self.state=self.expect_first_flow_mapping_keydefexpect_first_flow_mapping_key(self):ifisinstance(self.event,MappingEndEvent):self.indent=self.indents.pop()self.flow_level-=1self.write_indicator(u'}',False)self.state=self.states.pop()else:ifself.canonicalorself.column>self.best_width:self.write_indent()ifnotself.canonicalandself.check_simple_key():self.states.append(self.expect_flow_mapping_simple_value)self.expect_node(mapping=True,simple_key=True)else:self.write_indicator(u'?',True)self.states.append(self.expect_flow_mapping_value)self.expect_node(mapping=True)defexpect_flow_mapping_key(self):ifisinstance(self.event,MappingEndEvent):self.indent=self.indents.pop()self.flow_level-=1ifself.canonical:self.write_indicator(u',',False)self.write_indent()self.write_indicator(u'}',False)self.state=self.states.pop()else:self.write_indicator(u',',False)ifself.canonicalorself.column>self.best_width:self.write_indent()ifnotself.canonicalandself.check_simple_key():self.states.append(self.expect_flow_mapping_simple_value)self.expect_node(mapping=True,simple_key=True)else:self.write_indicator(u'?',True)self.states.append(self.expect_flow_mapping_value)self.expect_node(mapping=True)defexpect_flow_mapping_simple_value(self):self.write_indicator(u':',False)self.states.append(self.expect_flow_mapping_key)self.expect_node(mapping=True)defexpect_flow_mapping_value(self):ifself.canonicalorself.column>self.best_width:self.write_indent()self.write_indicator(u':',True)self.states.append(self.expect_flow_mapping_key)self.expect_node(mapping=True)# Block sequence handlers.defexpect_block_sequence(self):indentless=(self.mapping_contextandnotself.indention)self.increase_indent(flow=False,indentless=indentless)self.state=self.expect_first_block_sequence_itemdefexpect_first_block_sequence_item(self):returnself.expect_block_sequence_item(first=True)defexpect_block_sequence_item(self,first=False):ifnotfirstandisinstance(self.event,SequenceEndEvent):self.indent=self.indents.pop()self.state=self.states.pop()else:self.write_indent()self.write_indicator(u'-',True,indention=True)self.states.append(self.expect_block_sequence_item)self.expect_node(sequence=True)# Block mapping handlers.defexpect_block_mapping(self):self.increase_indent(flow=False)self.state=self.expect_first_block_mapping_keydefexpect_first_block_mapping_key(self):returnself.expect_block_mapping_key(first=True)defexpect_block_mapping_key(self,first=False):ifnotfirstandisinstance(self.event,MappingEndEvent):self.indent=self.indents.pop()self.state=self.states.pop()else:self.write_indent()ifself.check_simple_key():self.states.append(self.expect_block_mapping_simple_value)self.expect_node(mapping=True,simple_key=True)else:self.write_indicator(u'?',True,indention=True)self.states.append(self.expect_block_mapping_value)self.expect_node(mapping=True)defexpect_block_mapping_simple_value(self):self.write_indicator(u':',False)self.states.append(self.expect_block_mapping_key)self.expect_node(mapping=True)defexpect_block_mapping_value(self):self.write_indent()self.write_indicator(u':',True,indention=True)self.states.append(self.expect_block_mapping_key)self.expect_node(mapping=True)# Checkers.defcheck_empty_sequence(self):return(isinstance(self.event,SequenceStartEvent)andself.eventsandisinstance(self.events[0],SequenceEndEvent))defcheck_empty_mapping(self):return(isinstance(self.event,MappingStartEvent)andself.eventsandisinstance(self.events[0],MappingEndEvent))defcheck_empty_document(self):ifnotisinstance(self.event,DocumentStartEvent)ornotself.events:returnFalseevent=self.events[0]return(isinstance(event,ScalarEvent)andevent.anchorisNoneandevent.tagisNoneandevent.implicitandevent.value==u'')defcheck_simple_key(self):length=0ifisinstance(self.event,NodeEvent)andself.event.anchorisnotNone:ifself.prepared_anchorisNone:self.prepared_anchor=self.prepare_anchor(self.event.anchor)length+=len(self.prepared_anchor)ifisinstance(self.event,(ScalarEvent,CollectionStartEvent)) \
andself.event.tagisnotNone:ifself.prepared_tagisNone:self.prepared_tag=self.prepare_tag(self.event.tag)length+=len(self.prepared_tag)ifisinstance(self.event,ScalarEvent):ifself.analysisisNone:self.analysis=self.analyze_scalar(self.event.value)length+=len(self.analysis.scalar)return(length<128and(isinstance(self.event,AliasEvent)or(isinstance(self.event,ScalarEvent)andnotself.analysis.emptyandnotself.analysis.multiline)orself.check_empty_sequence()orself.check_empty_mapping()))# Anchor, Tag, and Scalar processors.defprocess_anchor(self,indicator):ifself.event.anchorisNone:self.prepared_anchor=Nonereturnifself.prepared_anchorisNone:self.prepared_anchor=self.prepare_anchor(self.event.anchor)ifself.prepared_anchor:self.write_indicator(indicator+self.prepared_anchor,True)self.prepared_anchor=Nonedefprocess_tag(self):tag=self.event.tagifisinstance(self.event,ScalarEvent):ifself.styleisNone:self.style=self.choose_scalar_style()if((notself.canonicalortagisNone)and((self.style==''andself.event.implicit[0])or(self.style!=''andself.event.implicit[1]))):self.prepared_tag=Nonereturnifself.event.implicit[0]andtagisNone:tag=u'!'self.prepared_tag=Noneelse:if(notself.canonicalortagisNone)andself.event.implicit:self.prepared_tag=NonereturniftagisNone:raiseEmitterError("tag is not specified")ifself.prepared_tagisNone:self.prepared_tag=self.prepare_tag(tag)ifself.prepared_tag:self.write_indicator(self.prepared_tag,True)self.prepared_tag=Nonedefchoose_scalar_style(self):ifself.analysisisNone:self.analysis=self.analyze_scalar(self.event.value)ifself.event.style=='"'orself.canonical:return'"'ifnotself.event.styleandself.event.implicit[0]:if(not(self.simple_key_contextand(self.analysis.emptyorself.analysis.multiline))and(self.flow_levelandself.analysis.allow_flow_plainor(notself.flow_levelandself.analysis.allow_block_plain))):return''ifself.event.styleandself.event.stylein'|>':ifnotself.flow_levelandself.analysis.allow_block:returnself.event.styleifnotself.event.styleorself.event.style=='\'':if(self.analysis.allow_single_quotedandnot(self.simple_key_contextandself.analysis.multiline)):return'\''return'"'defprocess_scalar(self):ifself.analysisisNone:self.analysis=self.analyze_scalar(self.event.value)ifself.styleisNone:self.style=self.choose_scalar_style()split=(notself.simple_key_context)#if self.analysis.multiline and split \# and (not self.style or self.style in '\'\"'):# self.write_indent()ifself.style=='"':self.write_double_quoted(self.analysis.scalar,split)elifself.style=='\'':self.write_single_quoted(self.analysis.scalar,split)elifself.style=='>':self.write_folded(self.analysis.scalar)elifself.style=='|':self.write_literal(self.analysis.scalar)else:self.write_plain(self.analysis.scalar,split)self.analysis=Noneself.style=None# Analyzers.defprepare_version(self,version):major,minor=versionifmajor!=1:raiseEmitterError("unsupported YAML version: %d.%d"%(major,minor))returnu'%d.%d'%(major,minor)defprepare_tag_handle(self,handle):ifnothandle:raiseEmitterError("tag handle must not be empty")ifhandle[0]!=u'!'orhandle[-1]!=u'!':raiseEmitterError("tag handle must start and end with '!': %r"%(handle.encode('utf-8')))forchinhandle[1:-1]:ifnot(u'0'<=ch<=u'9'oru'A'<=ch<='Z'oru'a'<=ch<='z' \
orchinu'-_'):raiseEmitterError("invalid character %r in the tag handle: %r"%(ch.encode('utf-8'),handle.encode('utf-8')))returnhandledefprepare_tag_prefix(self,prefix):ifnotprefix:raiseEmitterError("tag prefix must not be empty")chunks=[]start=end=0ifprefix[0]==u'!':end=1whileend<len(prefix):ch=prefix[end]ifu'0'<=ch<=u'9'oru'A'<=ch<='Z'oru'a'<=ch<='z' \
orchinu'-;/?!:@&=+$,_.~*\'()[]':end+=1else:ifstart<end:chunks.append(prefix[start:end])start=end=end+1data=ch.encode('utf-8')forchindata:chunks.append(u'%%%02X'%ord(ch))ifstart<end:chunks.append(prefix[start:end])returnu''.join(chunks)defprepare_tag(self,tag):ifnottag:raiseEmitterError("tag must not be empty")iftag==u'!':returntaghandle=Nonesuffix=tagforprefixinself.tag_prefixes:iftag.startswith(prefix) \
and(prefix==u'!'orlen(prefix)<len(tag)):handle=self.tag_prefixes[prefix]suffix=tag[len(prefix):]chunks=[]start=end=0whileend<len(suffix):ch=suffix[end]ifu'0'<=ch<=u'9'oru'A'<=ch<='Z'oru'a'<=ch<='z' \
orchinu'-;/?:@&=+$,_.~*\'()[]' \
or(ch==u'!'andhandle!=u'!'):end+=1else:ifstart<end:chunks.append(suffix[start:end])start=end=end+1data=ch.encode('utf-8')forchindata:chunks.append(u'%%%02X'%ord(ch))ifstart<end:chunks.append(suffix[start:end])suffix_text=u''.join(chunks)ifhandle:returnu'%s%s'%(handle,suffix_text)else:returnu'!<%s>'%suffix_textdefprepare_anchor(self,anchor):ifnotanchor:raiseEmitterError("anchor must not be empty")forchinanchor:ifnot(u'0'<=ch<=u'9'oru'A'<=ch<='Z'oru'a'<=ch<='z' \
orchinu'-_'):raiseEmitterError("invalid character %r in the anchor: %r"%(ch.encode('utf-8'),anchor.encode('utf-8')))returnanchordefanalyze_scalar(self,scalar):# Empty scalar is a special case.ifnotscalar:returnScalarAnalysis(scalar=scalar,empty=True,multiline=False,allow_flow_plain=False,allow_block_plain=True,allow_single_quoted=True,allow_double_quoted=True,allow_block=False)# Indicators and special characters.block_indicators=Falseflow_indicators=Falseline_breaks=Falsespecial_characters=False# Whitespaces.inline_spaces=False# non-space space+ non-spaceinline_breaks=False# non-space break+ non-spaceleading_spaces=False# ^ space+ (non-space | $)leading_breaks=False# ^ break+ (non-space | $)trailing_spaces=False# (^ | non-space) space+ $trailing_breaks=False# (^ | non-space) break+ $inline_breaks_spaces=False# non-space break+ space+ non-spacemixed_breaks_spaces=False# anything else# Check document indicators.ifscalar.startswith(u'---')orscalar.startswith(u'...'):block_indicators=Trueflow_indicators=True# First character or preceded by a whitespace.preceeded_by_space=True# Last character or followed by a whitespace.followed_by_space=(len(scalar)==1orscalar[1]inu'\0\t\r\n\x85\u2028\u2029')# The current series of whitespaces contain plain spaces.spaces=False# The current series of whitespaces contain line breaks.breaks=False# The current series of whitespaces contain a space followed by a# break.mixed=False# The current series of whitespaces start at the beginning of the# scalar.leading=Falseindex=0whileindex<len(scalar):ch=scalar[index]# Check for indicators.ifindex==0:# Leading indicators are special characters.ifchinu'#,[]{}#&*!|>\'\"%@`':flow_indicators=Trueblock_indicators=Trueifchinu'?:':flow_indicators=Trueiffollowed_by_space:block_indicators=Trueifch==u'-'andfollowed_by_space:flow_indicators=Trueblock_indicators=Trueelse:# Some indicators cannot appear within a scalar as well.ifchinu',?[]{}':flow_indicators=Trueifch==u':':flow_indicators=Trueiffollowed_by_space:block_indicators=Trueifch==u'#'andpreceeded_by_space:flow_indicators=Trueblock_indicators=True# Check for line breaks, special, and unicode characters.ifchinu'\n\x85\u2028\u2029':line_breaks=Trueifnot(ch==u'\n'oru'\x20'<=ch<=u'\x7E'):if(ch==u'\x85'oru'\xA0'<=ch<=u'\uD7FF'oru'\uE000'<=ch<=u'\uFFFD')andch!=u'\uFEFF':unicode_characters=Trueifnotself.allow_unicode:special_characters=Trueelse:special_characters=True# Spaces, line breaks, and how they are mixed. State machine.# Start or continue series of whitespaces.ifchinu' \n\x85\u2028\u2029':ifspacesandbreaks:ifch!=u' ':# break+ (space+ break+) => mixedmixed=Trueelifspaces:ifch!=u' ':# (space+ break+) => mixedbreaks=Truemixed=Trueelifbreaks:ifch==u' ':# break+ space+spaces=Trueelse:leading=(index==0)ifch==u' ':# space+spaces=Trueelse:# break+breaks=True# Series of whitespaces ended with a non-space.elifspacesorbreaks:ifleading:ifspacesandbreaks:mixed_breaks_spaces=Trueelifspaces:leading_spaces=Trueelifbreaks:leading_breaks=Trueelse:ifmixed:mixed_breaks_spaces=Trueelifspacesandbreaks:inline_breaks_spaces=Trueelifspaces:inline_spaces=Trueelifbreaks:inline_breaks=Truespaces=breaks=mixed=leading=False# Series of whitespaces reach the end.if(spacesorbreaks)and(index==len(scalar)-1):ifspacesandbreaks:mixed_breaks_spaces=Trueelifspaces:trailing_spaces=Trueifleading:leading_spaces=Trueelifbreaks:trailing_breaks=Trueifleading:leading_breaks=Truespaces=breaks=mixed=leading=False# Prepare for the next character.index+=1preceeded_by_space=(chinu'\0\t\r\n\x85\u2028\u2029')followed_by_space=(index+1>=len(scalar)orscalar[index+1]inu'\0\t\r\n\x85\u2028\u2029')# Let's decide what styles are allowed.allow_flow_plain=Trueallow_block_plain=Trueallow_single_quoted=Trueallow_double_quoted=Trueallow_block=True# Leading and trailing whitespace are bad for plain scalars. We also# do not want to mess with leading whitespaces for block scalars.ifleading_spacesorleading_breaksortrailing_spaces:allow_flow_plain=allow_block_plain=allow_block=False# Trailing breaks are fine for block scalars, but unacceptable for# plain scalars.iftrailing_breaks:allow_flow_plain=allow_block_plain=False# The combination of (space+ break+) is only acceptable for block# scalars.ifinline_breaks_spaces:allow_flow_plain=allow_block_plain=allow_single_quoted=False# Mixed spaces and breaks, as well as special character are only# allowed for double quoted scalars.ifmixed_breaks_spacesorspecial_characters:allow_flow_plain=allow_block_plain= \
allow_single_quoted=allow_block=False# We don't emit multiline plain scalars.ifline_breaks:allow_flow_plain=allow_block_plain=False# Flow indicators are forbidden for flow plain scalars.ifflow_indicators:allow_flow_plain=False# Block indicators are forbidden for block plain scalars.ifblock_indicators:allow_block_plain=FalsereturnScalarAnalysis(scalar=scalar,empty=False,multiline=line_breaks,allow_flow_plain=allow_flow_plain,allow_block_plain=allow_block_plain,allow_single_quoted=allow_single_quoted,allow_double_quoted=allow_double_quoted,allow_block=allow_block)# Writers.defflush_stream(self):ifhasattr(self.stream,'flush'):self.stream.flush()defwrite_stream_start(self):# Write BOM if needed.ifself.encodingandself.encoding.startswith('utf-16'):self.stream.write(u'\xFF\xFE'.encode(self.encoding))defwrite_stream_end(self):self.flush_stream()defwrite_indicator(self,indicator,need_whitespace,whitespace=False,indention=False):ifself.whitespaceornotneed_whitespace:data=indicatorelse:data=u' '+indicatorself.whitespace=whitespaceself.indention=self.indentionandindentionself.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)defwrite_indent(self):indent=self.indentor0ifnotself.indentionorself.column>indent \
or(self.column==indentandnotself.whitespace):self.write_line_break()ifself.column<indent:self.whitespace=Truedata=u' '*(indent-self.column)self.column=indentifself.encoding:data=data.encode(self.encoding)self.stream.write(data)defwrite_line_break(self,data=None):ifdataisNone:data=self.best_line_breakself.whitespace=Trueself.indention=Trueself.line+=1self.column=0ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)defwrite_version_directive(self,version_text):data=u'%%YAML %s'%version_textifself.encoding:data=data.encode(self.encoding)self.stream.write(data)self.write_line_break()defwrite_tag_directive(self,handle_text,prefix_text):data=u'%%TAG %s%s'%(handle_text,prefix_text)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)self.write_line_break()# Scalar streams.defwrite_single_quoted(self,text,split=True):self.write_indicator(u'\'',True)spaces=Falsebreaks=Falsestart=end=0whileend<=len(text):ch=Noneifend<len(text):ch=text[end]ifspaces:ifchisNoneorch!=u' ':ifstart+1==endandself.column>self.best_widthandsplit \
andstart!=0andend!=len(text):self.write_indent()else:data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endelifbreaks:ifchisNoneorchnotinu'\n\x85\u2028\u2029':iftext[start]==u'\n':self.write_line_break()forbrintext[start:end]:ifbr==u'\n':self.write_line_break()else:self.write_line_break(br)self.write_indent()start=endelse:ifchisNoneorchinu' \n\x85\u2028\u2029'orch==u'\'':ifstart<end:data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endifch==u'\'':data=u'\'\''self.column+=2ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=end+1ifchisnotNone:spaces=(ch==u' ')breaks=(chinu'\n\x85\u2028\u2029')end+=1self.write_indicator(u'\'',False)ESCAPE_REPLACEMENTS={u'\0':u'0',u'\x07':u'a',u'\x08':u'b',u'\x09':u't',u'\x0A':u'n',u'\x0B':u'v',u'\x0C':u'f',u'\x0D':u'r',u'\x1B':u'e',u'\"':u'\"',u'\\':u'\\',u'\x85':u'N',u'\xA0':u'_',u'\u2028':u'L',u'\u2029':u'P',}defwrite_double_quoted(self,text,split=True):self.write_indicator(u'"',True)start=end=0whileend<=len(text):ch=Noneifend<len(text):ch=text[end]ifchisNoneorchinu'"\\\x85\u2028\u2029\uFEFF' \
ornot(u'\x20'<=ch<=u'\x7E'or(self.allow_unicodeand(u'\xA0'<=ch<=u'\uD7FF'oru'\uE000'<=ch<=u'\uFFFD'))):ifstart<end:data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endifchisnotNone:ifchinself.ESCAPE_REPLACEMENTS:data=u'\\'+self.ESCAPE_REPLACEMENTS[ch]elifch<=u'\xFF':data=u'\\x%02X'%ord(ch)elifch<=u'\uFFFF':data=u'\\u%04X'%ord(ch)else:data=u'\\U%08X'%ord(ch)self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=end+1if0<end<len(text)-1and(ch==u' 'orstart>=end) \
andself.column+(end-start)>self.best_widthandsplit:data=text[start:end]+u'\\'ifstart<end:start=endself.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)self.write_indent()self.whitespace=Falseself.indention=Falseiftext[start]==u' ':data=u'\\'self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)end+=1self.write_indicator(u'"',False)defdetermine_chomp(self,text):tail=text[-2:]whilelen(tail)<2:tail=u' '+tailiftail[-1]inu'\n\x85\u2028\u2029':iftail[-2]inu'\n\x85\u2028\u2029':returnu'+'else:returnu''else:returnu'-'defwrite_folded(self,text):chomp=self.determine_chomp(text)self.write_indicator(u'>'+chomp,True)self.write_indent()leading_space=Falsespaces=Falsebreaks=Falsestart=end=0whileend<=len(text):ch=Noneifend<len(text):ch=text[end]ifbreaks:ifchisNoneorchnotinu'\n\x85\u2028\u2029':ifnotleading_spaceandchisnotNoneandch!=u' ' \
andtext[start]==u'\n':self.write_line_break()leading_space=(ch==u' ')forbrintext[start:end]:ifbr==u'\n':self.write_line_break()else:self.write_line_break(br)ifchisnotNone:self.write_indent()start=endelifspaces:ifch!=u' ':ifstart+1==endandself.column>self.best_width:self.write_indent()else:data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endelse:ifchisNoneorchinu' \n\x85\u2028\u2029':data=text[start:end]ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)ifchisNone:self.write_line_break()start=endifchisnotNone:breaks=(chinu'\n\x85\u2028\u2029')spaces=(ch==u' ')end+=1defwrite_literal(self,text):chomp=self.determine_chomp(text)self.write_indicator(u'|'+chomp,True)self.write_indent()breaks=Falsestart=end=0whileend<=len(text):ch=Noneifend<len(text):ch=text[end]ifbreaks:ifchisNoneorchnotinu'\n\x85\u2028\u2029':forbrintext[start:end]:ifbr==u'\n':self.write_line_break()else:self.write_line_break(br)ifchisnotNone:self.write_indent()start=endelse:ifchisNoneorchinu'\n\x85\u2028\u2029':data=text[start:end]ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)ifchisNone:self.write_line_break()start=endifchisnotNone:breaks=(chinu'\n\x85\u2028\u2029')end+=1defwrite_plain(self,text,split=True):ifnottext:returnifnotself.whitespace:data=u' 'self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)self.writespace=Falseself.indention=Falsespaces=Falsebreaks=Falsestart=end=0whileend<=len(text):ch=Noneifend<len(text):ch=text[end]ifspaces:ifch!=u' ':ifstart+1==endandself.column>self.best_widthandsplit:self.write_indent()self.writespace=Falseself.indention=Falseelse:data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endelifbreaks:ifchnotinu'\n\x85\u2028\u2029':iftext[start]==u'\n':self.write_line_break()forbrintext[start:end]:ifbr==u'\n':self.write_line_break()else:self.write_line_break(br)self.write_indent()self.whitespace=Falseself.indention=Falsestart=endelse:ifchisNoneorchinu' \n\x85\u2028\u2029':data=text[start:end]self.column+=len(data)ifself.encoding:data=data.encode(self.encoding)self.stream.write(data)start=endifchisnotNone:spaces=(ch==u' ')breaks=(chinu'\n\x85\u2028\u2029')end+=1