]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_vendor/pyparsing/exceptions.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _vendor / pyparsing / exceptions.py
1 # exceptions.py
2
3 import re
4 import sys
5 import typing
6
7 from .util import (
8 col,
9 line,
10 lineno,
11 _collapse_string_to_ranges,
12 replaced_by_pep8,
13 )
14 from .unicode import pyparsing_unicode as ppu
15
16
17 class ExceptionWordUnicode(ppu.Latin1, ppu.LatinA, ppu.LatinB, ppu.Greek, ppu.Cyrillic):
18 pass
19
20
21 _extract_alphanums = _collapse_string_to_ranges(ExceptionWordUnicode.alphanums)
22 _exception_word_extractor = re.compile("([" + _extract_alphanums + "]{1,16})|.")
23
24
25 class ParseBaseException(Exception):
26 """base exception class for all parsing runtime exceptions"""
27
28 loc: int
29 msg: str
30 pstr: str
31 parser_element: typing.Any # "ParserElement"
32 args: typing.Tuple[str, int, typing.Optional[str]]
33
34 __slots__ = (
35 "loc",
36 "msg",
37 "pstr",
38 "parser_element",
39 "args",
40 )
41
42 # Performance tuning: we construct a *lot* of these, so keep this
43 # constructor as small and fast as possible
44 def __init__(
45 self,
46 pstr: str,
47 loc: int = 0,
48 msg: typing.Optional[str] = None,
49 elem=None,
50 ):
51 self.loc = loc
52 if msg is None:
53 self.msg = pstr
54 self.pstr = ""
55 else:
56 self.msg = msg
57 self.pstr = pstr
58 self.parser_element = elem
59 self.args = (pstr, loc, msg)
60
61 @staticmethod
62 def explain_exception(exc, depth=16):
63 """
64 Method to take an exception and translate the Python internal traceback into a list
65 of the pyparsing expressions that caused the exception to be raised.
66
67 Parameters:
68
69 - exc - exception raised during parsing (need not be a ParseException, in support
70 of Python exceptions that might be raised in a parse action)
71 - depth (default=16) - number of levels back in the stack trace to list expression
72 and function names; if None, the full stack trace names will be listed; if 0, only
73 the failing input line, marker, and exception string will be shown
74
75 Returns a multi-line string listing the ParserElements and/or function names in the
76 exception's stack trace.
77 """
78 import inspect
79 from .core import ParserElement
80
81 if depth is None:
82 depth = sys.getrecursionlimit()
83 ret = []
84 if isinstance(exc, ParseBaseException):
85 ret.append(exc.line)
86 ret.append(" " * (exc.column - 1) + "^")
87 ret.append(f"{type(exc).__name__}: {exc}")
88
89 if depth > 0:
90 callers = inspect.getinnerframes(exc.__traceback__, context=depth)
91 seen = set()
92 for i, ff in enumerate(callers[-depth:]):
93 frm = ff[0]
94
95 f_self = frm.f_locals.get("self", None)
96 if isinstance(f_self, ParserElement):
97 if not frm.f_code.co_name.startswith(
98 ("parseImpl", "_parseNoCache")
99 ):
100 continue
101 if id(f_self) in seen:
102 continue
103 seen.add(id(f_self))
104
105 self_type = type(f_self)
106 ret.append(
107 f"{self_type.__module__}.{self_type.__name__} - {f_self}"
108 )
109
110 elif f_self is not None:
111 self_type = type(f_self)
112 ret.append(f"{self_type.__module__}.{self_type.__name__}")
113
114 else:
115 code = frm.f_code
116 if code.co_name in ("wrapper", "<module>"):
117 continue
118
119 ret.append(code.co_name)
120
121 depth -= 1
122 if not depth:
123 break
124
125 return "\n".join(ret)
126
127 @classmethod
128 def _from_exception(cls, pe):
129 """
130 internal factory method to simplify creating one type of ParseException
131 from another - avoids having __init__ signature conflicts among subclasses
132 """
133 return cls(pe.pstr, pe.loc, pe.msg, pe.parser_element)
134
135 @property
136 def line(self) -> str:
137 """
138 Return the line of text where the exception occurred.
139 """
140 return line(self.loc, self.pstr)
141
142 @property
143 def lineno(self) -> int:
144 """
145 Return the 1-based line number of text where the exception occurred.
146 """
147 return lineno(self.loc, self.pstr)
148
149 @property
150 def col(self) -> int:
151 """
152 Return the 1-based column on the line of text where the exception occurred.
153 """
154 return col(self.loc, self.pstr)
155
156 @property
157 def column(self) -> int:
158 """
159 Return the 1-based column on the line of text where the exception occurred.
160 """
161 return col(self.loc, self.pstr)
162
163 # pre-PEP8 compatibility
164 @property
165 def parserElement(self):
166 return self.parser_element
167
168 @parserElement.setter
169 def parserElement(self, elem):
170 self.parser_element = elem
171
172 def __str__(self) -> str:
173 if self.pstr:
174 if self.loc >= len(self.pstr):
175 foundstr = ", found end of text"
176 else:
177 # pull out next word at error location
178 found_match = _exception_word_extractor.match(self.pstr, self.loc)
179 if found_match is not None:
180 found = found_match.group(0)
181 else:
182 found = self.pstr[self.loc : self.loc + 1]
183 foundstr = (", found %r" % found).replace(r"\\", "\\")
184 else:
185 foundstr = ""
186 return f"{self.msg}{foundstr} (at char {self.loc}), (line:{self.lineno}, col:{self.column})"
187
188 def __repr__(self):
189 return str(self)
190
191 def mark_input_line(
192 self, marker_string: typing.Optional[str] = None, *, markerString: str = ">!<"
193 ) -> str:
194 """
195 Extracts the exception line from the input string, and marks
196 the location of the exception with a special symbol.
197 """
198 markerString = marker_string if marker_string is not None else markerString
199 line_str = self.line
200 line_column = self.column - 1
201 if markerString:
202 line_str = "".join(
203 (line_str[:line_column], markerString, line_str[line_column:])
204 )
205 return line_str.strip()
206
207 def explain(self, depth=16) -> str:
208 """
209 Method to translate the Python internal traceback into a list
210 of the pyparsing expressions that caused the exception to be raised.
211
212 Parameters:
213
214 - depth (default=16) - number of levels back in the stack trace to list expression
215 and function names; if None, the full stack trace names will be listed; if 0, only
216 the failing input line, marker, and exception string will be shown
217
218 Returns a multi-line string listing the ParserElements and/or function names in the
219 exception's stack trace.
220
221 Example::
222
223 expr = pp.Word(pp.nums) * 3
224 try:
225 expr.parse_string("123 456 A789")
226 except pp.ParseException as pe:
227 print(pe.explain(depth=0))
228
229 prints::
230
231 123 456 A789
232 ^
233 ParseException: Expected W:(0-9), found 'A' (at char 8), (line:1, col:9)
234
235 Note: the diagnostic output will include string representations of the expressions
236 that failed to parse. These representations will be more helpful if you use `set_name` to
237 give identifiable names to your expressions. Otherwise they will use the default string
238 forms, which may be cryptic to read.
239
240 Note: pyparsing's default truncation of exception tracebacks may also truncate the
241 stack of expressions that are displayed in the ``explain`` output. To get the full listing
242 of parser expressions, you may have to set ``ParserElement.verbose_stacktrace = True``
243 """
244 return self.explain_exception(self, depth)
245
246 # fmt: off
247 @replaced_by_pep8(mark_input_line)
248 def markInputline(self): ...
249 # fmt: on
250
251
252 class ParseException(ParseBaseException):
253 """
254 Exception thrown when a parse expression doesn't match the input string
255
256 Example::
257
258 try:
259 Word(nums).set_name("integer").parse_string("ABC")
260 except ParseException as pe:
261 print(pe)
262 print("column: {}".format(pe.column))
263
264 prints::
265
266 Expected integer (at char 0), (line:1, col:1)
267 column: 1
268
269 """
270
271
272 class ParseFatalException(ParseBaseException):
273 """
274 User-throwable exception thrown when inconsistent parse content
275 is found; stops all parsing immediately
276 """
277
278
279 class ParseSyntaxException(ParseFatalException):
280 """
281 Just like :class:`ParseFatalException`, but thrown internally
282 when an :class:`ErrorStop<And._ErrorStop>` ('-' operator) indicates
283 that parsing is to stop immediately because an unbacktrackable
284 syntax error has been found.
285 """
286
287
288 class RecursiveGrammarException(Exception):
289 """
290 Exception thrown by :class:`ParserElement.validate` if the
291 grammar could be left-recursive; parser may need to enable
292 left recursion using :class:`ParserElement.enable_left_recursion<ParserElement.enable_left_recursion>`
293 """
294
295 def __init__(self, parseElementList):
296 self.parseElementTrace = parseElementList
297
298 def __str__(self) -> str:
299 return f"RecursiveGrammarException: {self.parseElementTrace}"