from __future__ import absolute_import,print_function
_a='\x07'
_Z='\ufeff'
_Y='\ue000'
_X='\ud7ff'
_W='\x85'
_V='%%%02X'
_U='version'
_T="-;/?:@&=+$,_.~*'()[]"
_S='---'
_R=' \n\x85\u2028\u2029'
_Q='\xa0'
_P='a'
_O='0'
_N=','
_M='...'
_L='\\'
_K='['
_J="'"
_I='?'
_H='"'
_G='!'
_F='\n\x85\u2028\u2029'
_E='\n'
_D=' '
_C=False
_B=None
_A=True
import sys
from .error import YAMLError,YAMLStreamError
from .events import *
from .compat import utf8,text_type,PY2,nprint,dbg,DBG_EVENT,check_anchorname_char
if _C:from typing import Any,Dict,List,Union,Text,Tuple,Optional;from .compat import StreamType
__all__=['Emitter','EmitterError']
class EmitterError(YAMLError):0
class ScalarAnalysis:
	def __init__(self,scalar,empty,multiline,allow_flow_plain,allow_block_plain,allow_single_quoted,allow_double_quoted,allow_block):self.scalar=scalar;self.empty=empty;self.multiline=multiline;self.allow_flow_plain=allow_flow_plain;self.allow_block_plain=allow_block_plain;self.allow_single_quoted=allow_single_quoted;self.allow_double_quoted=allow_double_quoted;self.allow_block=allow_block
class Indents:
	def __init__(self):self.values=[]
	def append(self,val,seq):self.values.append((val,seq))
	def pop(self):return self.values.pop()[0]
	def last_seq(self):
		try:return self.values[-2][1]
		except IndexError:return _C
	def seq_flow_align(self,seq_indent,column):
		if len(self.values)<2 or not self.values[-1][1]:return 0
		base=self.values[-1][0]if self.values[-1][0]is not _B else 0;return base+seq_indent-column-1
	def __len__(self):return len(self.values)
class Emitter:
	DEFAULT_TAG_PREFIXES={_G:_G,'tag:yaml.org,2002:':'!!'};MAX_SIMPLE_KEY_LENGTH=128
	def __init__(self,stream,canonical=_B,indent=_B,width=_B,allow_unicode=_B,line_break=_B,block_seq_indent=_B,top_level_colon_align=_B,prefix_colon=_B,brace_single_entry_mapping_in_flow_sequence=_B,dumper=_B):
		self.dumper=dumper
		if self.dumper is not _B and getattr(self.dumper,'_emitter',_B)is _B:self.dumper._emitter=self
		self.stream=stream;self.encoding=_B;self.allow_space_break=_B;self.states=[];self.state=self.expect_stream_start;self.events=[];self.event=_B;self.indents=Indents();self.indent=_B;self.flow_context=[];self.root_context=_C;self.sequence_context=_C;self.mapping_context=_C;self.simple_key_context=_C;self.line=0;self.column=0;self.whitespace=_A;self.indention=_A;self.compact_seq_seq=_A;self.compact_seq_map=_A;self.no_newline=_B;self.open_ended=_C;self.colon=':';self.prefixed_colon=self.colon if prefix_colon is _B else prefix_colon+self.colon;self.brace_single_entry_mapping_in_flow_sequence=brace_single_entry_mapping_in_flow_sequence;self.canonical=canonical;self.allow_unicode=allow_unicode;self.unicode_supplementary=sys.maxunicode>65535;self.sequence_dash_offset=block_seq_indent if block_seq_indent else 0;self.top_level_colon_align=top_level_colon_align;self.best_sequence_indent=2;self.requested_indent=indent
		if indent and 1<indent<10:self.best_sequence_indent=indent
		self.best_map_indent=self.best_sequence_indent;self.best_width=80
		if width and width>self.best_sequence_indent*2:self.best_width=width
		self.best_line_break=_E
		if line_break in['\r',_E,'\r\n']:self.best_line_break=line_break
		self.tag_prefixes=_B;self.prepared_anchor=_B;self.prepared_tag=_B;self.analysis=_B;self.style=_B;self.scalar_after_indicator=_A
	@property
	def stream(self):
		try:return self._stream
		except AttributeError:raise YAMLStreamError('output stream needs to specified')
	@stream.setter
	def stream(self,val):
		if val is _B:return
		if not hasattr(val,'write'):raise YAMLStreamError('stream argument needs to have a write() method')
		self._stream=val
	@property
	def serializer(self):
		try:
			if hasattr(self.dumper,'typ'):return self.dumper.serializer
			return self.dumper._serializer
		except AttributeError:return self
	@property
	def flow_level(self):return len(self.flow_context)
	def dispose(self):self.states=[];self.state=_B
	def emit(self,event):
		if dbg(DBG_EVENT):nprint(event)
		self.events.append(event)
		while not self.need_more_events():self.event=self.events.pop(0);self.state();self.event=_B
	def need_more_events(self):
		if not self.events:return _A
		event=self.events[0]
		if isinstance(event,DocumentStartEvent):return self.need_events(1)
		elif isinstance(event,SequenceStartEvent):return self.need_events(2)
		elif isinstance(event,MappingStartEvent):return self.need_events(3)
		else:return _C
	def need_events(self,count):
		level=0
		for event in self.events[1:]:
			if isinstance(event,(DocumentStartEvent,CollectionStartEvent)):level+=1
			elif isinstance(event,(DocumentEndEvent,CollectionEndEvent)):level-=1
			elif isinstance(event,StreamEndEvent):level=-1
			if level<0:return _C
		return len(self.events)<count+1
	def increase_indent(self,flow=_C,sequence=_B,indentless=_C):
		self.indents.append(self.indent,sequence)
		if self.indent is _B:
			if flow:self.indent=self.requested_indent
			else:self.indent=0
		elif not indentless:self.indent+=self.best_sequence_indent if self.indents.last_seq()else self.best_map_indent
	def expect_stream_start(self):
		A='encoding'
		if isinstance(self.event,StreamStartEvent):
			if PY2:
				if self.event.encoding and not getattr(self.stream,A,_B):self.encoding=self.event.encoding
			elif self.event.encoding and not hasattr(self.stream,A):self.encoding=self.event.encoding
			self.write_stream_start();self.state=self.expect_first_document_start
		else:raise EmitterError('expected StreamStartEvent, but got %s'%(self.event,))
	def expect_nothing(self):raise EmitterError('expected nothing, but got %s'%(self.event,))
	def expect_first_document_start(self):return self.expect_document_start(first=_A)
	def expect_document_start(self,first=_C):
		if isinstance(self.event,DocumentStartEvent):
			if(self.event.version or self.event.tags)and self.open_ended:self.write_indicator(_M,_A);self.write_indent()
			if self.event.version:version_text=self.prepare_version(self.event.version);self.write_version_directive(version_text)
			self.tag_prefixes=self.DEFAULT_TAG_PREFIXES.copy()
			if self.event.tags:
				handles=sorted(self.event.tags.keys())
				for handle in handles:prefix=self.event.tags[handle];self.tag_prefixes[prefix]=handle;handle_text=self.prepare_tag_handle(handle);prefix_text=self.prepare_tag_prefix(prefix);self.write_tag_directive(handle_text,prefix_text)
			implicit=first and not self.event.explicit and not self.canonical and not self.event.version and not self.event.tags and not self.check_empty_document()
			if not implicit:
				self.write_indent();self.write_indicator(_S,_A)
				if self.canonical:self.write_indent()
			self.state=self.expect_document_root
		elif isinstance(self.event,StreamEndEvent):
			if self.open_ended:self.write_indicator(_M,_A);self.write_indent()
			self.write_stream_end();self.state=self.expect_nothing
		else:raise EmitterError('expected DocumentStartEvent, but got %s'%(self.event,))
	def expect_document_end(self):
		if isinstance(self.event,DocumentEndEvent):
			self.write_indent()
			if self.event.explicit:self.write_indicator(_M,_A);self.write_indent()
			self.flush_stream();self.state=self.expect_document_start
		else:raise EmitterError('expected DocumentEndEvent, but got %s'%(self.event,))
	def expect_document_root(self):self.states.append(self.expect_document_end);self.expect_node(root=_A)
	def expect_node(self,root=_C,sequence=_C,mapping=_C,simple_key=_C):
		self.root_context=root;self.sequence_context=sequence;self.mapping_context=mapping;self.simple_key_context=simple_key
		if isinstance(self.event,AliasEvent):self.expect_alias()
		elif isinstance(self.event,(ScalarEvent,CollectionStartEvent)):
			if self.process_anchor('&')and isinstance(self.event,ScalarEvent)and self.sequence_context:self.sequence_context=_C
			if root and isinstance(self.event,ScalarEvent)and not self.scalar_after_indicator:self.write_indent()
			self.process_tag()
			if isinstance(self.event,ScalarEvent):self.expect_scalar()
			elif isinstance(self.event,SequenceStartEvent):
				i2,n2=self.indention,self.no_newline
				if self.event.comment:
					if self.event.flow_style is _C and self.event.comment:
						if self.write_post_comment(self.event):self.indention=_C;self.no_newline=_A
					if self.write_pre_comment(self.event):self.indention=i2;self.no_newline=not self.indention
				if self.flow_level or self.canonical or self.event.flow_style or self.check_empty_sequence():self.expect_flow_sequence()
				else:self.expect_block_sequence()
			elif isinstance(self.event,MappingStartEvent):
				if self.event.flow_style is _C and self.event.comment:self.write_post_comment(self.event)
				if self.event.comment and self.event.comment[1]:self.write_pre_comment(self.event)
				if self.flow_level or self.canonical or self.event.flow_style or self.check_empty_mapping():self.expect_flow_mapping(single=self.event.nr_items==1)
				else:self.expect_block_mapping()
		else:raise EmitterError('expected NodeEvent, but got %s'%(self.event,))
	def expect_alias(self):
		if self.event.anchor is _B:raise EmitterError('anchor is not specified for alias')
		self.process_anchor('*');self.state=self.states.pop()
	def expect_scalar(self):self.increase_indent(flow=_A);self.process_scalar();self.indent=self.indents.pop();self.state=self.states.pop()
	def expect_flow_sequence(self):ind=self.indents.seq_flow_align(self.best_sequence_indent,self.column);self.write_indicator(_D*ind+_K,_A,whitespace=_A);self.increase_indent(flow=_A,sequence=_A);self.flow_context.append(_K);self.state=self.expect_first_flow_sequence_item
	def expect_first_flow_sequence_item(self):
		if isinstance(self.event,SequenceEndEvent):
			self.indent=self.indents.pop();popped=self.flow_context.pop();assert popped==_K;self.write_indicator(']',_C)
			if self.event.comment and self.event.comment[0]:self.write_post_comment(self.event)
			elif self.flow_level==0:self.write_line_break()
			self.state=self.states.pop()
		else:
			if self.canonical or self.column>self.best_width:self.write_indent()
			self.states.append(self.expect_flow_sequence_item);self.expect_node(sequence=_A)
	def expect_flow_sequence_item(self):
		if isinstance(self.event,SequenceEndEvent):
			self.indent=self.indents.pop();popped=self.flow_context.pop();assert popped==_K
			if self.canonical:self.write_indicator(_N,_C);self.write_indent()
			self.write_indicator(']',_C)
			if self.event.comment and self.event.comment[0]:self.write_post_comment(self.event)
			else:self.no_newline=_C
			self.state=self.states.pop()
		else:
			self.write_indicator(_N,_C)
			if self.canonical or self.column>self.best_width:self.write_indent()
			self.states.append(self.expect_flow_sequence_item);self.expect_node(sequence=_A)
	def expect_flow_mapping(self,single=_C):
		ind=self.indents.seq_flow_align(self.best_sequence_indent,self.column);map_init='{'
		if single and self.flow_level and self.flow_context[-1]==_K and not self.canonical and not self.brace_single_entry_mapping_in_flow_sequence:map_init=''
		self.write_indicator(_D*ind+map_init,_A,whitespace=_A);self.flow_context.append(map_init);self.increase_indent(flow=_A,sequence=_C);self.state=self.expect_first_flow_mapping_key
	def expect_first_flow_mapping_key(self):
		if isinstance(self.event,MappingEndEvent):
			self.indent=self.indents.pop();popped=self.flow_context.pop();assert popped=='{';self.write_indicator('}',_C)
			if self.event.comment and self.event.comment[0]:self.write_post_comment(self.event)
			elif self.flow_level==0:self.write_line_break()
			self.state=self.states.pop()
		else:
			if self.canonical or self.column>self.best_width:self.write_indent()
			if not self.canonical and self.check_simple_key():self.states.append(self.expect_flow_mapping_simple_value);self.expect_node(mapping=_A,simple_key=_A)
			else:self.write_indicator(_I,_A);self.states.append(self.expect_flow_mapping_value);self.expect_node(mapping=_A)
	def expect_flow_mapping_key(self):
		if isinstance(self.event,MappingEndEvent):
			self.indent=self.indents.pop();popped=self.flow_context.pop();assert popped in['{','']
			if self.canonical:self.write_indicator(_N,_C);self.write_indent()
			if popped!='':self.write_indicator('}',_C)
			if self.event.comment and self.event.comment[0]:self.write_post_comment(self.event)
			else:self.no_newline=_C
			self.state=self.states.pop()
		else:
			self.write_indicator(_N,_C)
			if self.canonical or self.column>self.best_width:self.write_indent()
			if not self.canonical and self.check_simple_key():self.states.append(self.expect_flow_mapping_simple_value);self.expect_node(mapping=_A,simple_key=_A)
			else:self.write_indicator(_I,_A);self.states.append(self.expect_flow_mapping_value);self.expect_node(mapping=_A)
	def expect_flow_mapping_simple_value(self):self.write_indicator(self.prefixed_colon,_C);self.states.append(self.expect_flow_mapping_key);self.expect_node(mapping=_A)
	def expect_flow_mapping_value(self):
		if self.canonical or self.column>self.best_width:self.write_indent()
		self.write_indicator(self.prefixed_colon,_A);self.states.append(self.expect_flow_mapping_key);self.expect_node(mapping=_A)
	def expect_block_sequence(self):
		if self.mapping_context:indentless=not self.indention
		else:
			indentless=_C
			if not self.compact_seq_seq and self.column!=0:self.write_line_break()
		self.increase_indent(flow=_C,sequence=_A,indentless=indentless);self.state=self.expect_first_block_sequence_item
	def expect_first_block_sequence_item(self):return self.expect_block_sequence_item(first=_A)
	def expect_block_sequence_item(self,first=_C):
		if not first and isinstance(self.event,SequenceEndEvent):
			if self.event.comment and self.event.comment[1]:self.write_pre_comment(self.event)
			self.indent=self.indents.pop();self.state=self.states.pop();self.no_newline=_C
		else:
			if self.event.comment and self.event.comment[1]:self.write_pre_comment(self.event)
			nonl=self.no_newline if self.column==0 else _C;self.write_indent();ind=self.sequence_dash_offset;self.write_indicator(_D*ind+'-',_A,indention=_A)
			if nonl or self.sequence_dash_offset+2>self.best_sequence_indent:self.no_newline=_A
			self.states.append(self.expect_block_sequence_item);self.expect_node(sequence=_A)
	def expect_block_mapping(self):
		if not self.mapping_context and not(self.compact_seq_map or self.column==0):self.write_line_break()
		self.increase_indent(flow=_C,sequence=_C);self.state=self.expect_first_block_mapping_key
	def expect_first_block_mapping_key(self):return self.expect_block_mapping_key(first=_A)
	def expect_block_mapping_key(self,first=_C):
		if not first and isinstance(self.event,MappingEndEvent):
			if self.event.comment and self.event.comment[1]:self.write_pre_comment(self.event)
			self.indent=self.indents.pop();self.state=self.states.pop()
		else:
			if self.event.comment and self.event.comment[1]:self.write_pre_comment(self.event)
			self.write_indent()
			if self.check_simple_key():
				if not isinstance(self.event,(SequenceStartEvent,MappingStartEvent)):
					try:
						if self.event.style==_I:self.write_indicator(_I,_A,indention=_A)
					except AttributeError:pass
				self.states.append(self.expect_block_mapping_simple_value);self.expect_node(mapping=_A,simple_key=_A)
				if isinstance(self.event,AliasEvent):self.stream.write(_D)
			else:self.write_indicator(_I,_A,indention=_A);self.states.append(self.expect_block_mapping_value);self.expect_node(mapping=_A)
	def expect_block_mapping_simple_value(self):
		if getattr(self.event,'style',_B)!=_I:
			if self.indent==0 and self.top_level_colon_align is not _B:c=_D*(self.top_level_colon_align-self.column)+self.colon
			else:c=self.prefixed_colon
			self.write_indicator(c,_C)
		self.states.append(self.expect_block_mapping_key);self.expect_node(mapping=_A)
	def expect_block_mapping_value(self):self.write_indent();self.write_indicator(self.prefixed_colon,_A,indention=_A);self.states.append(self.expect_block_mapping_key);self.expect_node(mapping=_A)
	def check_empty_sequence(self):return isinstance(self.event,SequenceStartEvent)and bool(self.events)and isinstance(self.events[0],SequenceEndEvent)
	def check_empty_mapping(self):return isinstance(self.event,MappingStartEvent)and bool(self.events)and isinstance(self.events[0],MappingEndEvent)
	def check_empty_document(self):
		if not isinstance(self.event,DocumentStartEvent)or not self.events:return _C
		event=self.events[0];return isinstance(event,ScalarEvent)and event.anchor is _B and event.tag is _B and event.implicit and event.value==''
	def check_simple_key(self):
		length=0
		if isinstance(self.event,NodeEvent)and self.event.anchor is not _B:
			if self.prepared_anchor is _B:self.prepared_anchor=self.prepare_anchor(self.event.anchor)
			length+=len(self.prepared_anchor)
		if isinstance(self.event,(ScalarEvent,CollectionStartEvent))and self.event.tag is not _B:
			if self.prepared_tag is _B:self.prepared_tag=self.prepare_tag(self.event.tag)
			length+=len(self.prepared_tag)
		if isinstance(self.event,ScalarEvent):
			if self.analysis is _B:self.analysis=self.analyze_scalar(self.event.value)
			length+=len(self.analysis.scalar)
		return length<self.MAX_SIMPLE_KEY_LENGTH and(isinstance(self.event,AliasEvent)or isinstance(self.event,SequenceStartEvent)and self.event.flow_style is _A or isinstance(self.event,MappingStartEvent)and self.event.flow_style is _A or isinstance(self.event,ScalarEvent)and not(self.analysis.empty and self.style and self.style not in'\'"')and not self.analysis.multiline or self.check_empty_sequence()or self.check_empty_mapping())
	def process_anchor(self,indicator):
		if self.event.anchor is _B:self.prepared_anchor=_B;return _C
		if self.prepared_anchor is _B:self.prepared_anchor=self.prepare_anchor(self.event.anchor)
		if self.prepared_anchor:self.write_indicator(indicator+self.prepared_anchor,_A);self.no_newline=_C
		self.prepared_anchor=_B;return _A
	def process_tag(self):
		tag=self.event.tag
		if isinstance(self.event,ScalarEvent):
			if self.style is _B:self.style=self.choose_scalar_style()
			if(not self.canonical or tag is _B)and(self.style==''and self.event.implicit[0]or self.style!=''and self.event.implicit[1]):self.prepared_tag=_B;return
			if self.event.implicit[0]and tag is _B:tag=_G;self.prepared_tag=_B
		elif(not self.canonical or tag is _B)and self.event.implicit:self.prepared_tag=_B;return
		if tag is _B:raise EmitterError('tag is not specified')
		if self.prepared_tag is _B:self.prepared_tag=self.prepare_tag(tag)
		if self.prepared_tag:
			self.write_indicator(self.prepared_tag,_A)
			if self.sequence_context and not self.flow_level and isinstance(self.event,ScalarEvent):self.no_newline=_A
		self.prepared_tag=_B
	def choose_scalar_style(self):
		if self.analysis is _B:self.analysis=self.analyze_scalar(self.event.value)
		if self.event.style==_H or self.canonical:return _H
		if(not self.event.style or self.event.style==_I)and(self.event.implicit[0]or not self.event.implicit[2]):
			if not(self.simple_key_context and(self.analysis.empty or self.analysis.multiline))and(self.flow_level and self.analysis.allow_flow_plain or not self.flow_level and self.analysis.allow_block_plain):return''
		self.analysis.allow_block=_A
		if self.event.style and self.event.style in'|>':
			if not self.flow_level and not self.simple_key_context and self.analysis.allow_block:return self.event.style
		if not self.event.style and self.analysis.allow_double_quoted:
			if _J in self.event.value or _E in self.event.value:return _H
		if not self.event.style or self.event.style==_J:
			if self.analysis.allow_single_quoted and not(self.simple_key_context and self.analysis.multiline):return _J
		return _H
	def process_scalar(self):
		if self.analysis is _B:self.analysis=self.analyze_scalar(self.event.value)
		if self.style is _B:self.style=self.choose_scalar_style()
		split=not self.simple_key_context
		if self.sequence_context and not self.flow_level:self.write_indent()
		if self.style==_H:self.write_double_quoted(self.analysis.scalar,split)
		elif self.style==_J:self.write_single_quoted(self.analysis.scalar,split)
		elif self.style=='>':self.write_folded(self.analysis.scalar)
		elif self.style=='|':self.write_literal(self.analysis.scalar,self.event.comment)
		else:self.write_plain(self.analysis.scalar,split)
		self.analysis=_B;self.style=_B
		if self.event.comment:self.write_post_comment(self.event)
	def prepare_version(self,version):
		major,minor=version
		if major!=1:raise EmitterError('unsupported YAML version: %d.%d'%(major,minor))
		return'%d.%d'%(major,minor)
	def prepare_tag_handle(self,handle):
		if not handle:raise EmitterError('tag handle must not be empty')
		if handle[0]!=_G or handle[-1]!=_G:raise EmitterError("tag handle must start and end with '!': %r"%utf8(handle))
		for ch in handle[1:-1]:
			if not(_O<=ch<='9'or'A'<=ch<='Z'or _P<=ch<='z'or ch in'-_'):raise EmitterError('invalid character %r in the tag handle: %r'%(utf8(ch),utf8(handle)))
		return handle
	def prepare_tag_prefix(self,prefix):
		if not prefix:raise EmitterError('tag prefix must not be empty')
		chunks=[];start=end=0
		if prefix[0]==_G:end=1
		ch_set=_T
		if self.dumper:
			version=getattr(self.dumper,_U,(1,2))
			if version is _B or version>=(1,2):ch_set+='#'
		while end<len(prefix):
			ch=prefix[end]
			if _O<=ch<='9'or'A'<=ch<='Z'or _P<=ch<='z'or ch in ch_set:end+=1
			else:
				if start<end:chunks.append(prefix[start:end])
				start=end=end+1;data=utf8(ch)
				for ch in data:chunks.append(_V%ord(ch))
		if start<end:chunks.append(prefix[start:end])
		return ''.join(chunks)
	def prepare_tag(self,tag):
		if not tag:raise EmitterError('tag must not be empty')
		if tag==_G:return tag
		handle=_B;suffix=tag;prefixes=sorted(self.tag_prefixes.keys())
		for prefix in prefixes:
			if tag.startswith(prefix)and(prefix==_G or len(prefix)<len(tag)):handle=self.tag_prefixes[prefix];suffix=tag[len(prefix):]
		chunks=[];start=end=0;ch_set=_T
		if self.dumper:
			version=getattr(self.dumper,_U,(1,2))
			if version is _B or version>=(1,2):ch_set+='#'
		while end<len(suffix):
			ch=suffix[end]
			if _O<=ch<='9'or'A'<=ch<='Z'or _P<=ch<='z'or ch in ch_set or ch==_G and handle!=_G:end+=1
			else:
				if start<end:chunks.append(suffix[start:end])
				start=end=end+1;data=utf8(ch)
				for ch in data:chunks.append(_V%ord(ch))
		if start<end:chunks.append(suffix[start:end])
		suffix_text=''.join(chunks)
		if handle:return'%s%s'%(handle,suffix_text)
		else:return'!<%s>'%suffix_text
	def prepare_anchor(self,anchor):
		if not anchor:raise EmitterError('anchor must not be empty')
		for ch in anchor:
			if not check_anchorname_char(ch):raise EmitterError('invalid character %r in the anchor: %r'%(utf8(ch),utf8(anchor)))
		return anchor
	def analyze_scalar(self,scalar):
		A='\x00 \t\r\n\x85\u2028\u2029'
		if not scalar:return ScalarAnalysis(scalar=scalar,empty=_A,multiline=_C,allow_flow_plain=_C,allow_block_plain=_A,allow_single_quoted=_A,allow_double_quoted=_A,allow_block=_C)
		block_indicators=_C;flow_indicators=_C;line_breaks=_C;special_characters=_C;leading_space=_C;leading_break=_C;trailing_space=_C;trailing_break=_C;break_space=_C;space_break=_C
		if scalar.startswith(_S)or scalar.startswith(_M):block_indicators=_A;flow_indicators=_A
		preceeded_by_whitespace=_A;followed_by_whitespace=len(scalar)==1 or scalar[1]in A;previous_space=_C;previous_break=_C;index=0
		while index<len(scalar):
			ch=scalar[index]
			if index==0:
				if ch in'#,[]{}&*!|>\'"%@`':flow_indicators=_A;block_indicators=_A
				if ch in'?:':
					if self.serializer.use_version==(1,1):flow_indicators=_A
					elif len(scalar)==1:flow_indicators=_A
					if followed_by_whitespace:block_indicators=_A
				if ch=='-'and followed_by_whitespace:flow_indicators=_A;block_indicators=_A
			else:
				if ch in',[]{}':flow_indicators=_A
				if ch==_I and self.serializer.use_version==(1,1):flow_indicators=_A
				if ch==':':
					if followed_by_whitespace:flow_indicators=_A;block_indicators=_A
				if ch=='#'and preceeded_by_whitespace:flow_indicators=_A;block_indicators=_A
			if ch in _F:line_breaks=_A
			if not(ch==_E or _D<=ch<='~'):
				if(ch==_W or _Q<=ch<=_X or _Y<=ch<='�'or self.unicode_supplementary and'𐀀'<=ch<='\U0010ffff')and ch!=_Z:
					if not self.allow_unicode:special_characters=_A
				else:special_characters=_A
			if ch==_D:
				if index==0:leading_space=_A
				if index==len(scalar)-1:trailing_space=_A
				if previous_break:break_space=_A
				previous_space=_A;previous_break=_C
			elif ch in _F:
				if index==0:leading_break=_A
				if index==len(scalar)-1:trailing_break=_A
				if previous_space:space_break=_A
				previous_space=_C;previous_break=_A
			else:previous_space=_C;previous_break=_C
			index+=1;preceeded_by_whitespace=ch in A;followed_by_whitespace=index+1>=len(scalar)or scalar[index+1]in A
		allow_flow_plain=_A;allow_block_plain=_A;allow_single_quoted=_A;allow_double_quoted=_A;allow_block=_A
		if leading_space or leading_break or trailing_space or trailing_break:allow_flow_plain=allow_block_plain=_C
		if trailing_space:allow_block=_C
		if break_space:allow_flow_plain=allow_block_plain=allow_single_quoted=_C
		if special_characters:allow_flow_plain=allow_block_plain=allow_single_quoted=allow_block=_C
		elif space_break:
			allow_flow_plain=allow_block_plain=allow_single_quoted=_C
			if not self.allow_space_break:allow_block=_C
		if line_breaks:allow_flow_plain=allow_block_plain=_C
		if flow_indicators:allow_flow_plain=_C
		if block_indicators:allow_block_plain=_C
		return ScalarAnalysis(scalar=scalar,empty=_C,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)
	def flush_stream(self):
		if hasattr(self.stream,'flush'):self.stream.flush()
	def write_stream_start(self):
		if self.encoding and self.encoding.startswith('utf-16'):self.stream.write(_Z.encode(self.encoding))
	def write_stream_end(self):self.flush_stream()
	def write_indicator(self,indicator,need_whitespace,whitespace=_C,indention=_C):
		if self.whitespace or not need_whitespace:data=indicator
		else:data=_D+indicator
		self.whitespace=whitespace;self.indention=self.indention and indention;self.column+=len(data);self.open_ended=_C
		if bool(self.encoding):data=data.encode(self.encoding)
		self.stream.write(data)
	def write_indent(self):
		indent=self.indent or 0
		if not self.indention or self.column>indent or self.column==indent and not self.whitespace:
			if bool(self.no_newline):self.no_newline=_C
			else:self.write_line_break()
		if self.column<indent:
			self.whitespace=_A;data=_D*(indent-self.column);self.column=indent
			if self.encoding:data=data.encode(self.encoding)
			self.stream.write(data)
	def write_line_break(self,data=_B):
		if data is _B:data=self.best_line_break
		self.whitespace=_A;self.indention=_A;self.line+=1;self.column=0
		if bool(self.encoding):data=data.encode(self.encoding)
		self.stream.write(data)
	def write_version_directive(self,version_text):
		data='%%YAML %s'%version_text
		if self.encoding:data=data.encode(self.encoding)
		self.stream.write(data);self.write_line_break()
	def write_tag_directive(self,handle_text,prefix_text):
		data='%%TAG %s %s'%(handle_text,prefix_text)
		if self.encoding:data=data.encode(self.encoding)
		self.stream.write(data);self.write_line_break()
	def write_single_quoted(self,text,split=_A):
		if self.root_context:
			if self.requested_indent is not _B:
				self.write_line_break()
				if self.requested_indent!=0:self.write_indent()
		self.write_indicator(_J,_A);spaces=_C;breaks=_C;start=end=0
		while end<=len(text):
			ch=_B
			if end<len(text):ch=text[end]
			if spaces:
				if ch is _B or ch!=_D:
					if start+1==end and self.column>self.best_width and split and start!=0 and end!=len(text):self.write_indent()
					else:
						data=text[start:end];self.column+=len(data)
						if bool(self.encoding):data=data.encode(self.encoding)
						self.stream.write(data)
					start=end
			elif breaks:
				if ch is _B or ch not in _F:
					if text[start]==_E:self.write_line_break()
					for br in text[start:end]:
						if br==_E:self.write_line_break()
						else:self.write_line_break(br)
					self.write_indent();start=end
			elif ch is _B or ch in _R or ch==_J:
				if start<end:
					data=text[start:end];self.column+=len(data)
					if bool(self.encoding):data=data.encode(self.encoding)
					self.stream.write(data);start=end
			if ch==_J:
				data="''";self.column+=2
				if bool(self.encoding):data=data.encode(self.encoding)
				self.stream.write(data);start=end+1
			if ch is not _B:spaces=ch==_D;breaks=ch in _F
			end+=1
		self.write_indicator(_J,_C)
	ESCAPE_REPLACEMENTS={'\x00':_O,_a:_P,'\x08':'b','\t':'t',_E:'n','\x0b':'v','\x0c':'f','\r':'r','\x1b':'e',_H:_H,_L:_L,_W:'N',_Q:'_','\u2028':'L','\u2029':'P'}
	def write_double_quoted(self,text,split=_A):
		if self.root_context:
			if self.requested_indent is not _B:
				self.write_line_break()
				if self.requested_indent!=0:self.write_indent()
		self.write_indicator(_H,_A);start=end=0
		while end<=len(text):
			ch=_B
			if end<len(text):ch=text[end]
			if ch is _B or ch in'"\\\x85\u2028\u2029\ufeff'or not(_D<=ch<='~'or self.allow_unicode and(_Q<=ch<=_X or _Y<=ch<='�')):
				if start<end:
					data=text[start:end];self.column+=len(data)
					if bool(self.encoding):data=data.encode(self.encoding)
					self.stream.write(data);start=end
				if ch is not _B:
					if ch in self.ESCAPE_REPLACEMENTS:data=_L+self.ESCAPE_REPLACEMENTS[ch]
					elif ch<='ÿ':data='\\x%02X'%ord(ch)
					elif ch<='\uffff':data='\\u%04X'%ord(ch)
					else:data='\\U%08X'%ord(ch)
					self.column+=len(data)
					if bool(self.encoding):data=data.encode(self.encoding)
					self.stream.write(data);start=end+1
			if 0<end<len(text)-1 and(ch==_D or start>=end)and self.column+(end-start)>self.best_width and split:
				data=text[start:end]+_L
				if start<end:start=end
				self.column+=len(data)
				if bool(self.encoding):data=data.encode(self.encoding)
				self.stream.write(data);self.write_indent();self.whitespace=_C;self.indention=_C
				if text[start]==_D:
					data=_L;self.column+=len(data)
					if bool(self.encoding):data=data.encode(self.encoding)
					self.stream.write(data)
			end+=1
		self.write_indicator(_H,_C)
	def determine_block_hints(self,text):
		indent=0;indicator='';hints=''
		if text:
			if text[0]in _R:indent=self.best_sequence_indent;hints+=text_type(indent)
			elif self.root_context:
				for end in ['\n---','\n...']:
					pos=0
					while _A:
						pos=text.find(end,pos)
						if pos==-1:break
						try:
							if text[pos+4]in' \r\n':break
						except IndexError:pass
						pos+=1
					if pos>-1:break
				if pos>0:indent=self.best_sequence_indent
			if text[-1]not in _F:indicator='-'
			elif len(text)==1 or text[-2]in _F:indicator='+'
		hints+=indicator;return hints,indent,indicator
	def write_folded(self,text):
		hints,_indent,_indicator=self.determine_block_hints(text);self.write_indicator('>'+hints,_A)
		if _indicator=='+':self.open_ended=_A
		self.write_line_break();leading_space=_A;spaces=_C;breaks=_A;start=end=0
		while end<=len(text):
			ch=_B
			if end<len(text):ch=text[end]
			if breaks:
				if ch is _B or ch not in'\n\x85\u2028\u2029\x07':
					if not leading_space and ch is not _B and ch!=_D and text[start]==_E:self.write_line_break()
					leading_space=ch==_D
					for br in text[start:end]:
						if br==_E:self.write_line_break()
						else:self.write_line_break(br)
					if ch is not _B:self.write_indent()
					start=end
			elif spaces:
				if ch!=_D:
					if start+1==end and self.column>self.best_width:self.write_indent()
					else:
						data=text[start:end];self.column+=len(data)
						if bool(self.encoding):data=data.encode(self.encoding)
						self.stream.write(data)
					start=end
			elif ch is _B or ch in' \n\x85\u2028\u2029\x07':
				data=text[start:end];self.column+=len(data)
				if bool(self.encoding):data=data.encode(self.encoding)
				self.stream.write(data)
				if ch==_a:
					if end<len(text)-1 and not text[end+2].isspace():self.write_line_break();self.write_indent();end+=2
					else:raise EmitterError('unexcpected fold indicator \\a before space')
				if ch is _B:self.write_line_break()
				start=end
			if ch is not _B:breaks=ch in _F;spaces=ch==_D
			end+=1
	def write_literal(self,text,comment=_B):
		hints,_indent,_indicator=self.determine_block_hints(text);self.write_indicator('|'+hints,_A)
		try:
			comment=comment[1][0]
			if comment:self.stream.write(comment)
		except (TypeError,IndexError):pass
		if _indicator=='+':self.open_ended=_A
		self.write_line_break();breaks=_A;start=end=0
		while end<=len(text):
			ch=_B
			if end<len(text):ch=text[end]
			if breaks:
				if ch is _B or ch not in _F:
					for br in text[start:end]:
						if br==_E:self.write_line_break()
						else:self.write_line_break(br)
					if ch is not _B:
						if self.root_context:idnx=self.indent if self.indent is not _B else 0;self.stream.write(_D*(_indent+idnx))
						else:self.write_indent()
					start=end
			elif ch is _B or ch in _F:
				data=text[start:end]
				if bool(self.encoding):data=data.encode(self.encoding)
				self.stream.write(data)
				if ch is _B:self.write_line_break()
				start=end
			if ch is not _B:breaks=ch in _F
			end+=1
	def write_plain(self,text,split=_A):
		if self.root_context:
			if self.requested_indent is not _B:
				self.write_line_break()
				if self.requested_indent!=0:self.write_indent()
			else:self.open_ended=_A
		if not text:return
		if not self.whitespace:
			data=_D;self.column+=len(data)
			if self.encoding:data=data.encode(self.encoding)
			self.stream.write(data)
		self.whitespace=_C;self.indention=_C;spaces=_C;breaks=_C;start=end=0
		while end<=len(text):
			ch=_B
			if end<len(text):ch=text[end]
			if spaces:
				if ch!=_D:
					if start+1==end and self.column>self.best_width and split:self.write_indent();self.whitespace=_C;self.indention=_C
					else:
						data=text[start:end];self.column+=len(data)
						if self.encoding:data=data.encode(self.encoding)
						self.stream.write(data)
					start=end
			elif breaks:
				if ch not in _F:
					if text[start]==_E:self.write_line_break()
					for br in text[start:end]:
						if br==_E:self.write_line_break()
						else:self.write_line_break(br)
					self.write_indent();self.whitespace=_C;self.indention=_C;start=end
			elif ch is _B or ch in _R:
				data=text[start:end];self.column+=len(data)
				if self.encoding:data=data.encode(self.encoding)
				try:self.stream.write(data)
				except:sys.stdout.write(repr(data)+_E);raise
				start=end
			if ch is not _B:spaces=ch==_D;breaks=ch in _F
			end+=1
	def write_comment(self,comment,pre=_C):
		value=comment.value
		if not pre and value[-1]==_E:value=value[:-1]
		try:
			col=comment.start_mark.column
			if comment.value and comment.value.startswith(_E):col=self.column
			elif col<self.column+1:ValueError
		except ValueError:col=self.column+1
		try:
			nr_spaces=col-self.column
			if self.column and value.strip()and nr_spaces<1 and value[0]!=_E:nr_spaces=1
			value=_D*nr_spaces+value
			try:
				if bool(self.encoding):value=value.encode(self.encoding)
			except UnicodeDecodeError:pass
			self.stream.write(value)
		except TypeError:raise
		if not pre:self.write_line_break()
	def write_pre_comment(self,event):
		comments=event.comment[1]
		if comments is _B:return _C
		try:
			start_events=MappingStartEvent,SequenceStartEvent
			for comment in comments:
				if isinstance(event,start_events)and getattr(comment,'pre_done',_B):continue
				if self.column!=0:self.write_line_break()
				self.write_comment(comment,pre=_A)
				if isinstance(event,start_events):comment.pre_done=_A
		except TypeError:sys.stdout.write('eventtt {} {}'.format(type(event),event));raise
		return _A
	def write_post_comment(self,event):
		if self.event.comment[0]is _B:return _C
		comment=event.comment[0];self.write_comment(comment);return _A