Changeset 52


Ignore:
Timestamp:
02/20/06 12:41:45 (9 years ago)
Author:
xi
Message:

Cleanup error messages.

Location:
branches/pyyaml3000
Files:
32 added
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/pyyaml3000/lib/yaml/error.py

    r45 r52  
     1 
     2__all__ = ['Marker', 'YAMLError', 'MarkedYAMLError'] 
     3 
     4class 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 
    143 
    244class YAMLError(Exception): 
    345    pass 
    446 
     47class 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  
    2121# flow_sequence_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)? 
    2222# 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 
    2427# Note that there is a slight deviation from the specification. We require a 
    2528# non-empty node content if ANCHOR or TAG is specified. This disallow such 
     
    5962# flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } 
    6063 
    61 from error import YAMLError 
     64from error import MarkedYAMLError 
    6265from tokens import * 
    6366from events import * 
    6467 
    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) 
     68class ParserError(MarkedYAMLError): 
     69    pass 
    8370 
    8471class Parser: 
     
    169156                if self.yaml_version is not None: 
    170157                    raise ParserError(None, None, 
    171                             "found duplicate YAML directive", token.start_marker()) 
     158                            "found duplicate YAML directive", token.start_marker) 
    172159                major, minor = token.value 
    173160                if major != 1: 
    174161                    raise ParserError(None, None, 
    175162                            "found incompatible YAML document (version 1.* is required)", 
    176                             token.start_marker()) 
     163                            token.start_marker) 
    177164                self.yaml_version = token.value 
    178165            elif token.name == u'TAG': 
     
    181168                    raise ParserError(None, None, 
    182169                            "duplicate tag handle %r" % handle.encode('utf-8'), 
    183                             token.start_marker()) 
     170                            token.start_marker) 
    184171                self.tag_handles[handle] = prefix 
    185172        for key in self.DEFAULT_TAGS: 
     
    394381            if self.scanner.check(FlowEntryToken): 
    395382                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) 
    400383        token = self.scanner.get() 
    401384        yield CollectionEndEvent(token.start_marker, token.end_marker) 
  • branches/pyyaml3000/lib/yaml/reader.py

    r48 r52  
    1616#   reader.line, stream.column - the line and the column of the current character. 
    1717 
    18 __all__ = ['Marker', 'Reader', 'ReaderError'] 
    19  
    20 from error import YAMLError 
     18__all__ = ['Reader', 'ReaderError'] 
     19 
     20from error import YAMLError, Marker 
    2121 
    2222import codecs, re 
     
    5656                data = data[:-count-1] 
    5757        return codecs.utf_8_decode(data, errors) 
    58  
    59 class Marker: 
    60  
    61     def __init__(self, name, line, column, buffer, pointer): 
    62         self.name = name 
    63         self.line = line 
    64         self.column = column 
    65         self.buffer = buffer 
    66         self.pointer = pointer 
    67  
    68     def get_snippet(self, indent=4, max_length=75): 
    69         if self.buffer is None: 
    70             return None 
    71         head = '' 
    72         start = self.pointer 
    73         while start > 0 and self.buffer[start-1] not in u'\0\r\n\x85\u2028\u2029': 
    74             start -= 1 
    75             if self.pointer-start > max_length/2-1: 
    76                 head = ' ... ' 
    77                 start += 5 
    78                 break 
    79         tail = '' 
    80         end = self.pointer 
    81         while end < len(self.buffer) and self.buffer[end] not in u'\0\r\n\x85\u2028\u2029': 
    82             end += 1 
    83             if end-self.pointer > max_length/2-1: 
    84                 tail = ' ... ' 
    85                 end -= 5 
    86                 break 
    87         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"+snippet 
    97         return where 
    9858 
    9959class ReaderError(YAMLError): 
  • branches/pyyaml3000/lib/yaml/scanner.py

    r51 r52  
    1111__all__ = ['Scanner', 'ScannerError'] 
    1212 
    13 from error import YAMLError 
     13from error import MarkedYAMLError 
    1414from tokens import * 
    1515 
    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) 
     16class ScannerError(MarkedYAMLError): 
     17    pass 
    4218 
    4319class SimpleKey: 
     
    197173        if ch == u'.' and self.check_document_end(): 
    198174            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 
    199179 
    200180        # Note: the order of the following checks is NOT significant. 
     
    750730        # specification requires. Any such mark will be considered as a part 
    751731        # 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 
    752744        if self.reader.index == 0 and self.reader.peek() == u'\uFEFF': 
    753745            self.reader.forward() 
     
    794786        if not length: 
    795787            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()) 
    798790        value = self.reader.prefix(length) 
    799791        self.reader.forward(length) 
    800792        ch = self.reader.peek() 
    801793        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, 
    803795                    "expected alphabetic or numeric character, but found %r" 
    804796                    % ch.encode('utf-8'), self.reader.get_marker()) 
     
    812804        if self.reader.peek() != '.': 
    813805            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'), 
    815808                    self.reader.get_marker()) 
    816809        self.reader.forward() 
     
    818811        if self.reader.peek() not in u'\0 \r\n\x85\u2028\u2029': 
    819812            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'), 
    821815                    self.reader.get_marker()) 
    822816        return (major, minor) 
     
    849843        # See the specification for details. 
    850844        value = self.scan_tag_handle('directive', start_marker) 
    851         if self.reader.peek() != u' ': 
     845        ch = self.reader.peek() 
     846        if ch != u' ': 
    852847            raise ScannerError("while scanning a directive", start_marker, 
    853848                    "expected ' ', but found %r" % ch.encode('utf-8'), 
     
    903898        if not length: 
    904899            raise ScannerError("while scanning an %s" % name, start_marker, 
    905                     "expected anchor 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()) 
    907902        value = self.reader.prefix(length) 
    908903        self.reader.forward(length) 
     
    924919            suffix = self.scan_tag_uri('tag', start_marker) 
    925920            if self.reader.peek() != u'>': 
    926                 raise ScannerError("while parsing a tag", start_marking, 
    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'), 
    928923                        self.reader.get_marker()) 
    929924            self.reader.forward() 
     
    13101305        # For some strange reasons, the specification does not allow '_' in 
    13111306        # tag handles. I have allowed it anyway. 
    1312         if self.reader.peek() != u'!': 
     1307        ch = self.reader.peek() 
     1308        if ch != u'!': 
    13131309            raise ScannerError("while scanning a %s" % name, start_marker, 
    13141310                    "expected '!', but found %r" % ch.encode('utf-8'), 
  • branches/pyyaml3000/lib/yaml/tokens.py

    r51 r52  
    3636 
    3737class BlockMappingStartToken(Token): 
    38     id = '<block mapping end>' 
     38    id = '<block mapping start>' 
    3939 
    4040class BlockEndToken(Token): 
  • branches/pyyaml3000/tests/data/unclosed-bracket.error-message

    r47 r52  
    11test: 
    22    - [ 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  
    33 
    44from yaml.error import YAMLError 
    5 from yaml.reader import Reader 
    6 from yaml.scanner import Scanner 
     5from yaml.reader import * 
     6from yaml.scanner import * 
     7from yaml.parser import * 
    78 
    89class TestErrors(test_appliance.TestAppliance): 
     
    1718 
    1819    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 
    2231 
    2332    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 
    2745 
    2846TestErrors.add_tests('testErrors', '.error-message') 
  • branches/pyyaml3000/tests/test_syck.py

    r51 r52  
    22import test_appliance 
    33 
    4 from yaml.reader import * 
    5 from yaml.tokens import * 
    6 from yaml.scanner import * 
     4class TestSyck(test_appliance.TestAppliance): 
    75 
    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): 
    537        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')) 
    619        except: 
    6210            print 
    6311            print "DATA:" 
    6412            print file(data_filename, 'rb').read() 
    65             print "TOKENS1:", tokens1 
    66             print "TOKENS2:", tokens2 
    6713            raise 
    6814 
    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 
    7023 
    71 class TestScanner(test_appliance.TestAppliance): 
     24try: 
     25    import syck 
     26    #TestSyck.add_tests('testSyckOnTokenTests', '.data', '.tokens') 
     27    #TestSyck.add_tests('testSyckOnCanonicalTests', '.data', '.canonical') 
     28except ImportError: 
     29    pass 
    7230 
    73     def _testScanner(self, test_name, data_filename, canonical_filename): 
    74         for filename in [canonical_filename, data_filename]: 
    75             tokens = None 
    76             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                 print 
    84                 print "DATA:" 
    85                 print file(data_filename, 'rb').read() 
    86                 print "TOKENS:", tokens 
    87                 raise 
    88  
    89 TestScanner.add_tests('testScanner', '.data', '.canonical') 
    90  
  • branches/pyyaml3000/tests/test_yaml.py

    r47 r52  
    88from test_structure import * 
    99from test_errors import * 
     10from test_syck import * 
    1011 
    1112def main(module='__main__'): 
Note: See TracChangeset for help on using the changeset viewer.