summaryrefslogtreecommitdiff
path: root/pyparsing/exceptions.py
diff options
context:
space:
mode:
authorPaul McGuire <ptmcg@users.noreply.github.com>2020-03-31 22:06:28 -0500
committerPaul McGuire <ptmcg@users.noreply.github.com>2020-03-31 22:06:28 -0500
commit7eae92192cd93aa1bf1205f4a141d89414aef937 (patch)
tree5555a399fdd13a81a2838f6df6a9e2f94e20f3e8 /pyparsing/exceptions.py
parent90f6fa2703e3117723864d08bccc310638b1d645 (diff)
downloadpyparsing-git-7eae92192cd93aa1bf1205f4a141d89414aef937.tar.gz
Refactor ParseException explain() static method into a staticmethod and an instance method on ParseBaseException
Diffstat (limited to 'pyparsing/exceptions.py')
-rw-r--r--pyparsing/exceptions.py160
1 files changed, 87 insertions, 73 deletions
diff --git a/pyparsing/exceptions.py b/pyparsing/exceptions.py
index fbed072..e5f665f 100644
--- a/pyparsing/exceptions.py
+++ b/pyparsing/exceptions.py
@@ -19,6 +19,77 @@ class ParseBaseException(Exception):
self.parserElement = elem
self.args = (pstr, loc, msg)
+ @staticmethod
+ def explain_exception(exc, depth=16):
+ """
+ Method to take an exception and translate the Python internal traceback into a list
+ of the pyparsing expressions that caused the exception to be raised.
+
+ Parameters:
+
+ - exc - exception raised during parsing (need not be a ParseException, in support
+ of Python exceptions that might be raised in a parse action)
+ - depth (default=16) - number of levels back in the stack trace to list expression
+ and function names; if None, the full stack trace names will be listed; if 0, only
+ the failing input line, marker, and exception string will be shown
+
+ Returns a multi-line string listing the ParserElements and/or function names in the
+ exception's stack trace.
+
+ Note: the diagnostic output will include string representations of the expressions
+ that failed to parse. These representations will be more helpful if you use `setName` to
+ give identifiable names to your expressions. Otherwise they will use the default string
+ forms, which may be cryptic to read.
+ """
+ import inspect
+ from .core import ParserElement
+
+ if depth is None:
+ depth = sys.getrecursionlimit()
+ ret = []
+ if isinstance(exc, ParseBaseException):
+ ret.append(exc.line)
+ ret.append(" " * (exc.col - 1) + "^")
+ ret.append("{}: {}".format(type(exc).__name__, exc))
+
+ if depth > 0:
+ callers = inspect.getinnerframes(exc.__traceback__, context=depth)
+ seen = set()
+ for i, ff in enumerate(callers[-depth:]):
+ frm = ff[0]
+
+ f_self = frm.f_locals.get("self", None)
+ if isinstance(f_self, ParserElement):
+ if frm.f_code.co_name not in ("parseImpl", "_parseNoCache"):
+ continue
+ if f_self in seen:
+ continue
+ seen.add(f_self)
+
+ self_type = type(f_self)
+ ret.append(
+ "{}.{} - {}".format(
+ self_type.__module__, self_type.__name__, f_self
+ )
+ )
+
+ elif f_self is not None:
+ self_type = type(f_self)
+ ret.append("{}.{}".format(self_type.__module__, self_type.__name__))
+
+ else:
+ code = frm.f_code
+ if code.co_name in ("wrapper", "<module>"):
+ continue
+
+ ret.append("{}".format(code.co_name))
+
+ depth -= 1
+ if not depth:
+ break
+
+ return "\n".join(ret)
+
@classmethod
def _from_exception(cls, pe):
"""
@@ -78,6 +149,22 @@ class ParseBaseException(Exception):
def __dir__(self):
return "lineno col line".split() + dir(type(self))
+ def explain(self, depth=16):
+ """
+ Method to translate the Python internal traceback into a list
+ of the pyparsing expressions that caused the exception to be raised.
+
+ Parameters:
+
+ - depth (default=16) - number of levels back in the stack trace to list expression
+ and function names; if None, the full stack trace names will be listed; if 0, only
+ the failing input line, marker, and exception string will be shown
+
+ Returns a multi-line string listing the ParserElements and/or function names in the
+ exception's stack trace.
+ """
+ return self.explain_exception(self, depth)
+
class ParseException(ParseBaseException):
"""
@@ -102,79 +189,6 @@ class ParseException(ParseBaseException):
"""
- @staticmethod
- def explain(exc, depth=16):
- """
- Method to take an exception and translate the Python internal traceback into a list
- of the pyparsing expressions that caused the exception to be raised.
-
- Parameters:
-
- - exc - exception raised during parsing (need not be a ParseException, in support
- of Python exceptions that might be raised in a parse action)
- - depth (default=16) - number of levels back in the stack trace to list expression
- and function names; if None, the full stack trace names will be listed; if 0, only
- the failing input line, marker, and exception string will be shown
-
- Returns a multi-line string listing the ParserElements and/or function names in the
- exception's stack trace.
-
- Note: the diagnostic output will include string representations of the expressions
- that failed to parse. These representations will be more helpful if you use `setName` to
- give identifiable names to your expressions. Otherwise they will use the default string
- forms, which may be cryptic to read.
-
- explain() is only supported under Python 3.
- """
- import inspect
- from .core import ParserElement
-
- if depth is None:
- depth = sys.getrecursionlimit()
- ret = []
- if isinstance(exc, ParseBaseException):
- ret.append(exc.line)
- ret.append(" " * (exc.col - 1) + "^")
- ret.append("{}: {}".format(type(exc).__name__, exc))
-
- if depth > 0:
- callers = inspect.getinnerframes(exc.__traceback__, context=depth)
- seen = set()
- for i, ff in enumerate(callers[-depth:]):
- frm = ff[0]
-
- f_self = frm.f_locals.get("self", None)
- if isinstance(f_self, ParserElement):
- if frm.f_code.co_name not in ("parseImpl", "_parseNoCache"):
- continue
- if f_self in seen:
- continue
- seen.add(f_self)
-
- self_type = type(f_self)
- ret.append(
- "{}.{} - {}".format(
- self_type.__module__, self_type.__name__, f_self
- )
- )
-
- elif f_self is not None:
- self_type = type(f_self)
- ret.append("{}.{}".format(self_type.__module__, self_type.__name__))
-
- else:
- code = frm.f_code
- if code.co_name in ("wrapper", "<module>"):
- continue
-
- ret.append("{}".format(code.co_name))
-
- depth -= 1
- if not depth:
- break
-
- return "\n".join(ret)
-
class ParseFatalException(ParseBaseException):
"""user-throwable exception thrown when inconsistent parse content