bazarr/libs/dynaconf/vendor/ruamel/yaml/emitter.py

671 lines
35 KiB
Python
Raw Blame History

from __future__ import absolute_import,print_function
_T='\ufeff'
_S='\ue000'
_R='\ud7ff'
_Q='%%%02X'
_P='version'
_O="-;/?:@&=+$,_.~*'()[]"
_N=' \n\x85\u2028\u2029'
_M='\xa0'
_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(_L,_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('---',_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(_L,_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(_L,_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+'[',_A,whitespace=_A);self.increase_indent(flow=_A,sequence=_A);self.flow_context.append('[');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=='[';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=='['
if self.canonical:self.write_indicator(',',_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(',',_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]=='['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(',',_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(',',_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('0'<=ch<='9'or'A'<=ch<='Z'or'a'<=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=_O
if self.dumper:
version=getattr(self.dumper,_P,(1,2))
if version is _B or version>=(1,2):ch_set+='#'
while end<len(prefix):
ch=prefix[end]
if'0'<=ch<='9'or'A'<=ch<='Z'or'a'<=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(_Q%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=_O
if self.dumper:
version=getattr(self.dumper,_P,(1,2))
if version is _B or version>=(1,2):ch_set+='#'
while end<len(suffix):
ch=suffix[end]
if'0'<=ch<='9'or'A'<=ch<='Z'or'a'<=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(_Q%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('---')or scalar.startswith(_L):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=='\x85'or _M<=ch<=_R or _S<=ch<='<EFBFBD>'or self.unicode_supplementary and'𐀀'<=ch<='\U0010ffff')and ch!=_T:
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(_T.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 _N 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':'0','\x07':'a','\x08':'b','\t':'t',_E:'n','\x0b':'v','\x0c':'f','\r':'r','\x1b':'e',_H:_H,_K:_K,'\x85':'N',_M:'_','\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(_M<=ch<=_R or _S<=ch<='<EFBFBD>')):
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=_K+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]+_K
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=_K;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 _N: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=='\x07':
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 _N:
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