File: error.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (136 lines) | stat: -rw-r--r-- 5,540 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from rpython.rlib.objectmodel import specialize
from pypy.interpreter.unicodehelper import _str_decode_utf8_slowpath

def wrap_pos(space, num):
    if num <= 0:
        return space.w_None
    return space.newint(num)

@specialize.memo()
def make_replace_error_handler(space):
    def replace_error_handler(errors, encoding, msg, w_s, startpos, endpos):
        return b'\xef\xbf\xbd', endpos, 'b', space.bytes_w(w_s), w_s
    return replace_error_handler

def _adjust_offset(space, offset, text, unilength):
    if offset > len(text):
        offset = unilength
    elif offset >= 1:
        offset = offset - 1 # 1-based to 0-based
        assert offset >= 0
        # slightly inefficient, call the decoder for text[:offset] too
        s = text[:offset]
        w_s = space.newbytes(s)
        _, offset, _ = _str_decode_utf8_slowpath(space, 
                s, w_s, 'replace', False, make_replace_error_handler(space),
                True)
        offset += 1 # convert to 1-based
    else:
        offset = 0
    return offset

class SyntaxError(Exception):
    """Base class for exceptions raised by the parser."""

    def __init__(self, msg, lineno=0, offset=0, text=None, filename=None,
                 end_lineno=0, end_offset=0):
        self.msg = msg
        self.lineno = lineno
        # NB: offset and end_offset are 1-based indexes into the bytes source
        self.offset = offset
        self.text = text
        self.filename = filename
        self.end_lineno = end_lineno
        self.end_offset = end_offset

    @staticmethod
    def fromast(msg, node, filename=None):
        return SyntaxError(msg, node.lineno, node.col_offset + 1,
                           filename=filename,
                           end_lineno=node.end_lineno,
                           end_offset=node.end_col_offset + 1)

    def find_sourceline_and_wrap_info(self, space, source=None, filename=None):
        """ search for the line of input that caused the error and then return
        a wrapped tuple that can be used to construct a wrapped SyntaxError.
        Optionally pass source, to get better error messages for the case where
        this instance was constructed without a source line (.text
        attribute)"""
        text = self.text
        if text is None and source is not None and self.lineno:
            lines = source.splitlines(True)
            text = lines[self.lineno - 1]
        w_text = w_filename = space.w_None
        w_lineno = space.newint(self.lineno)
        if filename is None:
            filename = self.filename
        if filename is not None:
            w_filename = space.newfilename(filename)
            if text is None:
                w_text = space.appexec([w_filename, w_lineno],
                    """(filename, lineno):
                    try:
                        with open(filename) as f:
                            for _ in range(lineno - 1):
                                f.readline()
                            return f.readline()
                    except:  # we can't allow any exceptions here!
                        return None""")
        offset = self.offset
        end_offset = self.end_offset
        if text is not None:
            # text may not be UTF-8 in case of decoding errors.
            # adjust the encoded text offset to a decoded offset
            # XXX do the right thing about continuation lines, which
            # XXX are their own fun, sometimes giving offset >
            # XXX len(text) for example (right now, avoid crashing)

            # this also converts the byte-based self.offset to a
            # codepoint-based index into the decoded unicode-version of
            # self.text

            replacedtext, unilength, _ = _str_decode_utf8_slowpath(space,
                    text, space.newbytes(text), 'replace', False, make_replace_error_handler(space), True)
            offset = _adjust_offset(space, offset, text, unilength)
            # XXX this is wrong if end_lineno != lineno
            end_offset = _adjust_offset(space, end_offset, text, unilength)
            w_text = space.newutf8(replacedtext, unilength)
        return space.newtuple([
            space.newtext(self.msg),
            space.newtuple([
                w_filename, w_lineno, wrap_pos(space, offset),
                w_text, wrap_pos(space, self.end_lineno),
                wrap_pos(space, end_offset)])])

    def __str__(self):
        return "%s at pos (%d, %d) in %r" % (
            self.__class__.__name__, self.lineno, self.offset, self.text)

class IndentationError(SyntaxError):
    pass

class TabError(IndentationError):
    def __init__(self, lineno=0, offset=0, text=None, filename=None,
                 end_lineno=0, end_offset=0):
        msg = "inconsistent use of tabs and spaces in indentation"
        IndentationError.__init__(
            self, msg, lineno, offset, text, filename, end_lineno, end_offset)

class ASTError(Exception):
    def __init__(self, msg, ast_node):
        self.msg = msg
        self.ast_node = ast_node


class TokenError(SyntaxError):

    def __init__(self, msg, line, lineno, column, tokens, end_lineno=0, end_offset=0):
        SyntaxError.__init__(self, msg, lineno, column, line,
                             end_lineno=end_lineno, end_offset=end_offset)
        self.tokens = tokens

class TokenIndentationError(IndentationError):

    def __init__(self, msg, line, lineno, column, tokens):
        SyntaxError.__init__(self, msg, lineno, column, line)
        self.tokens = tokens