Changeset 52
- Timestamp:
- 02/20/06 12:41:45 (6 years ago)
- Location:
- branches/pyyaml3000
- Files:
-
- 32 added
- 8 modified
- 1 copied
-
lib/yaml/error.py (modified) (1 diff)
-
lib/yaml/parser.py (modified) (5 diffs)
-
lib/yaml/reader.py (modified) (2 diffs)
-
lib/yaml/scanner.py (modified) (10 diffs)
-
lib/yaml/tokens.py (modified) (1 diff)
-
tests/data/duplicate-tag-directive.error-message (added)
-
tests/data/duplicate-yaml-directive.error-message (added)
-
tests/data/invalid-anchor-1.error-message (added)
-
tests/data/invalid-anchor-2.error-message (added)
-
tests/data/invalid-directive-line.error-message (added)
-
tests/data/invalid-directive-name-1.error-message (added)
-
tests/data/invalid-directive-name-2.error-message (added)
-
tests/data/invalid-tag-1.error-message (added)
-
tests/data/invalid-tag-2.error-message (added)
-
tests/data/invalid-tag-directive-handle.error-message (added)
-
tests/data/invalid-tag-directive-prefix.error-message (added)
-
tests/data/invalid-tag-handle-1.error-message (added)
-
tests/data/invalid-tag-handle-2.error-message (added)
-
tests/data/invalid-uri-escapes-1.error-message (added)
-
tests/data/invalid-uri-escapes-2.error-message (added)
-
tests/data/invalid-uri-escapes-3.error-message (added)
-
tests/data/invalid-uri.error-message (added)
-
tests/data/invalid-yaml-directive-version-1.error-message (added)
-
tests/data/invalid-yaml-directive-version-2.error-message (added)
-
tests/data/invalid-yaml-directive-version-3.error-message (added)
-
tests/data/invalid-yaml-directive-version-4.error-message (added)
-
tests/data/invalid-yaml-directive-version-5.error-message (added)
-
tests/data/invalid-yaml-directive-version-6.error-message (added)
-
tests/data/invalid-yaml-version.error-message (added)
-
tests/data/no-block-collection-end.error-message (added)
-
tests/data/no-block-mapping-end.error-message (added)
-
tests/data/no-document-start.error-message (added)
-
tests/data/no-flow-mapping-end.error-message (added)
-
tests/data/no-flow-sequence-end.error-message (added)
-
tests/data/no-node-1.error-message (added)
-
tests/data/no-node-2.error-message (added)
-
tests/data/unclosed-bracket.error-message (modified) (1 diff)
-
tests/data/undefined-tag-handle.error-message (added)
-
tests/test_errors.py (modified) (2 diffs)
-
tests/test_syck.py (copied) (copied from branches/pyyaml3000/tests/test_tokens.py) (1 diff)
-
tests/test_yaml.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/pyyaml3000/lib/yaml/error.py
r45 r52 1 2 __all__ = ['Marker', 'YAMLError', 'MarkedYAMLError'] 3 4 class Marker: 5 6 def __init__(self, name, line, column, buffer, pointer): 7 self.name = name 8 self.line = line 9 self.column = column 10 self.buffer = buffer 11 self.pointer = pointer 12 13 def get_snippet(self, indent=4, max_length=75): 14 if self.buffer is None: 15 return None 16 head = '' 17 start = self.pointer 18 while start > 0 and self.buffer[start-1] not in u'\0\r\n\x85\u2028\u2029': 19 start -= 1 20 if self.pointer-start > max_length/2-1: 21 head = ' ... ' 22 start += 5 23 break 24 tail = '' 25 end = self.pointer 26 while end < len(self.buffer) and self.buffer[end] not in u'\0\r\n\x85\u2028\u2029': 27 end += 1 28 if end-self.pointer > max_length/2-1: 29 tail = ' ... ' 30 end -= 5 31 break 32 snippet = self.buffer[start:end].encode('utf-8') 33 return ' '*indent + head + snippet + tail + '\n' \ 34 + ' '*(indent+self.pointer-start+len(head)) + '^' 35 36 def __str__(self): 37 snippet = self.get_snippet() 38 where = " in \"%s\", line %d, column %d" \ 39 % (self.name, self.line+1, self.column+1) 40 if snippet is not None: 41 where += ":\n"+snippet 42 return where 1 43 2 44 class YAMLError(Exception): 3 45 pass 4 46 47 class MarkedYAMLError(YAMLError): 48 49 def __init__(self, context=None, context_marker=None, 50 problem=None, problem_marker=None): 51 self.context = context 52 self.context_marker = context_marker 53 self.problem = problem 54 self.problem_marker = problem_marker 55 56 def __str__(self): 57 lines = [] 58 #for (place, marker) in [(self.context, self.context_marker), 59 # (self.problem, self.problem_marker)]: 60 # if place is not None: 61 # lines.append(place) 62 # if marker is not None: 63 # lines.append(str(marker)) 64 if self.context is not None: 65 lines.append(self.context) 66 if self.context_marker is not None \ 67 and (self.problem is None or self.problem_marker is None 68 or self.context_marker.name != self.problem_marker.name 69 or self.context_marker.line != self.problem_marker.line 70 or self.context_marker.column != self.problem_marker.column): 71 lines.append(str(self.context_marker)) 72 if self.problem is not None: 73 lines.append(self.problem) 74 if self.problem_marker is not None: 75 lines.append(str(self.problem_marker)) 76 return '\n'.join(lines) 77 78 79 -
branches/pyyaml3000/lib/yaml/parser.py
r51 r52 21 21 # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 22 22 # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 23 # 23 24 # TODO: support for BOM within a stream. 25 # stream ::= (BOM? implicit_document)? (BOM? explicit_document)* STREAM-END 26 24 27 # Note that there is a slight deviation from the specification. We require a 25 28 # non-empty node content if ANCHOR or TAG is specified. This disallow such … … 59 62 # flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } 60 63 61 from error import YAMLError64 from error import MarkedYAMLError 62 65 from tokens import * 63 66 from events import * 64 67 65 class ParserError(YAMLError): 66 67 def __init__(self, context=None, context_marker=None, 68 problem=None, problem_marker=None): 69 self.context = context 70 self.context_marker = context_marker 71 self.problem = problem 72 self.problem_marker = problem_marker 73 74 def __str__(self): 75 lines = [] 76 for (place, marker) in [(self.context, self.context_marker), 77 (self.problem, self.problem_marker)]: 78 if place is not None: 79 lines.append(place) 80 if marker is not None: 81 lines.append(str(marker)) 82 return '\n'.join(lines) 68 class ParserError(MarkedYAMLError): 69 pass 83 70 84 71 class Parser: … … 169 156 if self.yaml_version is not None: 170 157 raise ParserError(None, None, 171 "found duplicate YAML directive", token.start_marker ())158 "found duplicate YAML directive", token.start_marker) 172 159 major, minor = token.value 173 160 if major != 1: 174 161 raise ParserError(None, None, 175 162 "found incompatible YAML document (version 1.* is required)", 176 token.start_marker ())163 token.start_marker) 177 164 self.yaml_version = token.value 178 165 elif token.name == u'TAG': … … 181 168 raise ParserError(None, None, 182 169 "duplicate tag handle %r" % handle.encode('utf-8'), 183 token.start_marker ())170 token.start_marker) 184 171 self.tag_handles[handle] = prefix 185 172 for key in self.DEFAULT_TAGS: … … 394 381 if self.scanner.check(FlowEntryToken): 395 382 self.scanner.get() 396 if not self.scanner.check(FlowSequenceEndToken):397 token = self.scanner.peek()398 raise ParserError("while scanning a flow sequence", start_marker,399 "expected ']', but found %r" % token.id, token.start_marker)400 383 token = self.scanner.get() 401 384 yield CollectionEndEvent(token.start_marker, token.end_marker) -
branches/pyyaml3000/lib/yaml/reader.py
r48 r52 16 16 # reader.line, stream.column - the line and the column of the current character. 17 17 18 __all__ = [' Marker', 'Reader', 'ReaderError']19 20 from error import YAMLError 18 __all__ = ['Reader', 'ReaderError'] 19 20 from error import YAMLError, Marker 21 21 22 22 import codecs, re … … 56 56 data = data[:-count-1] 57 57 return codecs.utf_8_decode(data, errors) 58 59 class Marker:60 61 def __init__(self, name, line, column, buffer, pointer):62 self.name = name63 self.line = line64 self.column = column65 self.buffer = buffer66 self.pointer = pointer67 68 def get_snippet(self, indent=4, max_length=75):69 if self.buffer is None:70 return None71 head = ''72 start = self.pointer73 while start > 0 and self.buffer[start-1] not in u'\0\r\n\x85\u2028\u2029':74 start -= 175 if self.pointer-start > max_length/2-1:76 head = ' ... '77 start += 578 break79 tail = ''80 end = self.pointer81 while end < len(self.buffer) and self.buffer[end] not in u'\0\r\n\x85\u2028\u2029':82 end += 183 if end-self.pointer > max_length/2-1:84 tail = ' ... '85 end -= 586 break87 snippet = self.buffer[start:end].encode('utf-8')88 return ' '*indent + head + snippet + tail + '\n' \89 + ' '*(indent+self.pointer-start+len(head)) + '^'90 91 def __str__(self):92 snippet = self.get_snippet()93 where = " in \"%s\", line %d, column %d" \94 % (self.name, self.line+1, self.column+1)95 if snippet is not None:96 where += ":\n"+snippet97 return where98 58 99 59 class ReaderError(YAMLError): -
branches/pyyaml3000/lib/yaml/scanner.py
r51 r52 11 11 __all__ = ['Scanner', 'ScannerError'] 12 12 13 from error import YAMLError13 from error import MarkedYAMLError 14 14 from tokens import * 15 15 16 class ScannerError(YAMLError): 17 # ScannerError: while reading a quoted string 18 # in '...', line 5, column 10: 19 # key: "valu\?e" 20 # ^ 21 # got unknown quote character '?' 22 # in '...', line 5, column 15: 23 # key: "valu\?e" 24 # ^ 25 26 def __init__(self, context=None, context_marker=None, 27 problem=None, problem_marker=None): 28 self.context = context 29 self.context_marker = context_marker 30 self.problem = problem 31 self.problem_marker = problem_marker 32 33 def __str__(self): 34 lines = [] 35 for (place, marker) in [(self.context, self.context_marker), 36 (self.problem, self.problem_marker)]: 37 if place is not None: 38 lines.append(place) 39 if marker is not None: 40 lines.append(str(marker)) 41 return '\n'.join(lines) 16 class ScannerError(MarkedYAMLError): 17 pass 42 18 43 19 class SimpleKey: … … 197 173 if ch == u'.' and self.check_document_end(): 198 174 return self.fetch_document_end() 175 176 # TODO: support for BOM within a stream. 177 #if ch == u'\uFEFF': 178 # return self.fetch_bom() <-- issue BOMToken 199 179 200 180 # Note: the order of the following checks is NOT significant. … … 750 730 # specification requires. Any such mark will be considered as a part 751 731 # of the document. 732 # 733 # TODO: We need to make tab handling rules more sane. A good rule is 734 # Tabs cannot precede tokens 735 # BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END, 736 # KEY(block), VALUE(block), BLOCK-ENTRY 737 # So the checking code is 738 # if <TAB>: 739 # self.allow_simple_keys = False 740 # We also need to add the check for `allow_simple_keys == True` to 741 # `unwind_indent` before issuing BLOCK-END. 742 # Scanners for block, flow, and plain scalars need to be modified. 743 752 744 if self.reader.index == 0 and self.reader.peek() == u'\uFEFF': 753 745 self.reader.forward() … … 794 786 if not length: 795 787 raise ScannerError("while scanning a directive", start_marker, 796 "expected directive name, but found %r" % ch.encode('utf-8'),797 self.reader.get_marker())788 "expected alphabetic or numeric character, but found %r" 789 % ch.encode('utf-8'), self.reader.get_marker()) 798 790 value = self.reader.prefix(length) 799 791 self.reader.forward(length) 800 792 ch = self.reader.peek() 801 793 if ch not in u'\0 \r\n\x85\u2028\u2029': 802 raise ScannerError("while scanning a directive" % name, start_marker,794 raise ScannerError("while scanning a directive", start_marker, 803 795 "expected alphabetic or numeric character, but found %r" 804 796 % ch.encode('utf-8'), self.reader.get_marker()) … … 812 804 if self.reader.peek() != '.': 813 805 raise ScannerError("while scanning a directive", start_marker, 814 "expected a digit or '.', but found %r" % ch.encode('utf-8'), 806 "expected a digit or '.', but found %r" 807 % self.reader.peek().encode('utf-8'), 815 808 self.reader.get_marker()) 816 809 self.reader.forward() … … 818 811 if self.reader.peek() not in u'\0 \r\n\x85\u2028\u2029': 819 812 raise ScannerError("while scanning a directive", start_marker, 820 "expected a digit or ' ', but found %r" % ch.encode('utf-8'), 813 "expected a digit or ' ', but found %r" 814 % self.reader.peek().encode('utf-8'), 821 815 self.reader.get_marker()) 822 816 return (major, minor) … … 849 843 # See the specification for details. 850 844 value = self.scan_tag_handle('directive', start_marker) 851 if self.reader.peek() != u' ': 845 ch = self.reader.peek() 846 if ch != u' ': 852 847 raise ScannerError("while scanning a directive", start_marker, 853 848 "expected ' ', but found %r" % ch.encode('utf-8'), … … 903 898 if not length: 904 899 raise ScannerError("while scanning an %s" % name, start_marker, 905 "expected a nchor name, but found %r" % ch.encode('utf-8'),906 self.reader.get_marker())900 "expected alphabetic or numeric character, but found %r" 901 % ch.encode('utf-8'), self.reader.get_marker()) 907 902 value = self.reader.prefix(length) 908 903 self.reader.forward(length) … … 924 919 suffix = self.scan_tag_uri('tag', start_marker) 925 920 if self.reader.peek() != u'>': 926 raise ScannerError("while parsing a tag", start_mark ing,927 "expected '>', but got%r" % self.reader.peek().encode('utf-8'),921 raise ScannerError("while parsing a tag", start_marker, 922 "expected '>', but found %r" % self.reader.peek().encode('utf-8'), 928 923 self.reader.get_marker()) 929 924 self.reader.forward() … … 1310 1305 # For some strange reasons, the specification does not allow '_' in 1311 1306 # tag handles. I have allowed it anyway. 1312 if self.reader.peek() != u'!': 1307 ch = self.reader.peek() 1308 if ch != u'!': 1313 1309 raise ScannerError("while scanning a %s" % name, start_marker, 1314 1310 "expected '!', but found %r" % ch.encode('utf-8'), -
branches/pyyaml3000/lib/yaml/tokens.py
r51 r52 36 36 37 37 class BlockMappingStartToken(Token): 38 id = '<block mapping end>'38 id = '<block mapping start>' 39 39 40 40 class BlockEndToken(Token): -
branches/pyyaml3000/tests/data/unclosed-bracket.error-message
r47 r52 1 1 test: 2 2 - [ foo: bar 3 - baz 4 "we could have detected the unclosed bracket on the above line, but this would forbid such syntax as": { 5 } 3 # comment the rest of the stream to let the scanner detect the problem. 4 # - baz 5 #"we could have detected the unclosed bracket on the above line, but this would forbid such syntax as": { 6 #} -
branches/pyyaml3000/tests/test_errors.py
r51 r52 3 3 4 4 from yaml.error import YAMLError 5 from yaml.reader import Reader 6 from yaml.scanner import Scanner 5 from yaml.reader import * 6 from yaml.scanner import * 7 from yaml.parser import * 7 8 8 9 class TestErrors(test_appliance.TestAppliance): … … 17 18 18 19 def _load(self, filename): 19 reader = Reader(file(filename, 'rb')) 20 scanner = Scanner(reader) 21 return list(scanner) 20 try: 21 reader = Reader(file(filename, 'rb')) 22 scanner = Scanner(reader) 23 parser = Parser(scanner) 24 return list(parser) 25 except YAMLError, exc: 26 #except ScannerError, exc: 27 #except ParserError, exc: 28 #print '.'*70 29 #print "%s:" % exc.__class__.__name__, exc 30 raise 22 31 23 32 def _load_string(self, filename): 24 reader = Reader(file(filename, 'rb').read()) 25 scanner = Scanner(reader) 26 return list(scanner) 33 try: 34 reader = Reader(file(filename, 'rb').read()) 35 scanner = Scanner(reader) 36 parser = Parser(scanner) 37 return list(parser) 38 except YAMLError, exc: 39 #except ScannerError, exc: 40 #except ParserError, exc: 41 #print '.'*70 42 #print "%s:" % filename 43 #print "%s:" % exc.__class__.__name__, exc 44 raise 27 45 28 46 TestErrors.add_tests('testErrors', '.error-message') -
branches/pyyaml3000/tests/test_syck.py
r51 r52 2 2 import test_appliance 3 3 4 from yaml.reader import * 5 from yaml.tokens import * 6 from yaml.scanner import * 4 class TestSyck(test_appliance.TestAppliance): 7 5 8 class TestTokens(test_appliance.TestAppliance): 9 10 # Tokens mnemonic: 11 # directive: % 12 # document_start: --- 13 # document_end: ... 14 # alias: * 15 # anchor: & 16 # tag: ! 17 # scalar _ 18 # block_sequence_start: [[ 19 # block_mapping_start: {{ 20 # block_end: ]} 21 # flow_sequence_start: [ 22 # flow_sequence_end: ] 23 # flow_mapping_start: { 24 # flow_mapping_end: } 25 # entry: , 26 # key: ? 27 # value: : 28 29 replaces = { 30 DirectiveToken: '%', 31 DocumentStartToken: '---', 32 DocumentEndToken: '...', 33 AliasToken: '*', 34 AnchorToken: '&', 35 TagToken: '!', 36 ScalarToken: '_', 37 BlockSequenceStartToken: '[[', 38 BlockMappingStartToken: '{{', 39 BlockEndToken: ']}', 40 FlowSequenceStartToken: '[', 41 FlowSequenceEndToken: ']', 42 FlowMappingStartToken: '{', 43 FlowMappingEndToken: '}', 44 BlockEntryToken: ',', 45 FlowEntryToken: ',', 46 KeyToken: '?', 47 ValueToken: ':', 48 } 49 50 def _testTokens(self, test_name, data_filename, tokens_filename): 51 tokens1 = None 52 tokens2 = file(tokens_filename, 'rb').read().split() 6 def _testSyckOnTokenTests(self, test_name, data_filename, tokens_filename): 53 7 try: 54 scanner = Scanner(Reader(file(data_filename, 'rb'))) 55 tokens1 = [] 56 for token in scanner: 57 if not isinstance(token, StreamEndToken): 58 tokens1.append(token) 59 tokens1 = [self.replaces[t.__class__] for t in tokens1] 60 self.failUnlessEqual(tokens1, tokens2) 8 syck.parse(file(data_filename, 'rb')) 61 9 except: 62 10 print 63 11 print "DATA:" 64 12 print file(data_filename, 'rb').read() 65 print "TOKENS1:", tokens166 print "TOKENS2:", tokens267 13 raise 68 14 69 TestTokens.add_tests('testTokens', '.data', '.tokens') 15 def _testSyckOnCanonicalTests(self, test_name, data_filename, canonical_filename): 16 try: 17 syck.parse(file(data_filename, 'rb')) 18 except: 19 print 20 print "DATA:" 21 print file(data_filename, 'rb').read() 22 raise 70 23 71 class TestScanner(test_appliance.TestAppliance): 24 try: 25 import syck 26 #TestSyck.add_tests('testSyckOnTokenTests', '.data', '.tokens') 27 #TestSyck.add_tests('testSyckOnCanonicalTests', '.data', '.canonical') 28 except ImportError: 29 pass 72 30 73 def _testScanner(self, test_name, data_filename, canonical_filename):74 for filename in [canonical_filename, data_filename]:75 tokens = None76 try:77 scanner = Scanner(Reader(file(filename, 'rb')))78 tokens = []79 for token in scanner:80 if not isinstance(token, StreamEndToken):81 tokens.append(token.__class__.__name__)82 except:83 print84 print "DATA:"85 print file(data_filename, 'rb').read()86 print "TOKENS:", tokens87 raise88 89 TestScanner.add_tests('testScanner', '.data', '.canonical')90 -
branches/pyyaml3000/tests/test_yaml.py
r47 r52 8 8 from test_structure import * 9 9 from test_errors import * 10 from test_syck import * 10 11 11 12 def main(module='__main__'):
