python (3.11.7)

(root)/
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 ESC[4;38;5;81mExceptionWordUnicode(ESC[4;38;5;149mppuESC[4;38;5;149m.ESC[4;38;5;149mLatin1, ESC[4;38;5;149mppuESC[4;38;5;149m.ESC[4;38;5;149mLatinA, ESC[4;38;5;149mppuESC[4;38;5;149m.ESC[4;38;5;149mLatinB, ESC[4;38;5;149mppuESC[4;38;5;149m.ESC[4;38;5;149mGreek, ESC[4;38;5;149mppuESC[4;38;5;149m.ESC[4;38;5;149mCyrillic):
      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 ESC[4;38;5;81mParseBaseException(ESC[4;38;5;149mException):
      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 ESC[4;38;5;81mParseException(ESC[4;38;5;149mParseBaseException):
     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 ESC[4;38;5;81mParseFatalException(ESC[4;38;5;149mParseBaseException):
     273      """
     274      User-throwable exception thrown when inconsistent parse content
     275      is found; stops all parsing immediately
     276      """
     277  
     278  
     279  class ESC[4;38;5;81mParseSyntaxException(ESC[4;38;5;149mParseFatalException):
     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 ESC[4;38;5;81mRecursiveGrammarException(ESC[4;38;5;149mException):
     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}"