3030class ConsoleBase (QTextEdit ):
3131 """Base class for a text widget used to show stdout/stderr writes."""
3232
33- workbox_pattern = re .compile (
34- r'File "<Workbox(?:Selection)?>:(?P<workboxName>.*)", '
35- r'line (?P<lineNum>\d{1,6})'
36- r'(?P<inStr>, in)?'
37- )
38- """For Traceback workbox lines, use this regex pattern, so we can extract
39- workboxName and lineNum. Note that Syntax errors present slightly
40- differently than other Exceptions.
41- SyntaxErrors:
42- - Do NOT include the text ", in" followed by a module
43- - DO include the offending line of code
44- Other Exceptions
45- - DO include the text ", in" followed by a module
46- - Do NOT include the offending line of code if from stdIn (ie
47- a workbox)
48- So we will use the presence of the text ", in" to tell use whether to
49- fake the offending code line or not.
50- """
51-
52- traceback_pattern = re .compile (
53- r'File "(?P<filename>.*)", line (?P<lineNum>\d{1,10})(, in|\r\n|\n|$)'
54- )
55- """A pattern to capture info from tracebacks. The newline/$ section
56- handle SyntaxError output that does not include the `, in ...` portion."""
57-
5833 def __init__ (self , parent : QWidget , controller : Optional [LoggerWindow ] = None ):
5934 super ().__init__ (parent )
6035 self .controller = controller
@@ -80,6 +55,48 @@ def __repr__(self):
8055
8156 return f"<{ module } .{ class_ } { name } object at 0x{ id (self ):016X} >"
8257
58+ @classmethod
59+ def __defineRegexPatterns (cls ):
60+ """Define various regex patterns to use to determine if the msg to write
61+ is part of a traceback, and also to determine if it is from a workbox, or
62+ from the console.
63+
64+ We construct various parts of the patterns, and combine them into the
65+ final patterns. The workbox pattern and console pattern share the line
66+ and in_str parts.
67+ """
68+
69+ # For Traceback workbox lines, use this regex pattern, so we can extract
70+ # workboxName and lineNum. Note that Syntax errors present slightly
71+ # differently than other Exceptions.
72+ # SyntaxErrors:
73+ # - Do NOT include the text ", in" followed by a module
74+ # - DO include the offending line of code
75+ # Other Exceptions
76+ # - DO include the text ", in" followed by a module
77+ # - Do NOT include the offending line of code if from stdIn (ie
78+ # a workbox)
79+ # So we will use the presence of the text ", in" to tell use whether to
80+ # fake the offending code line or not.
81+
82+ # Define pattern pieces
83+ console_pattern = r'File "<ConsolePrEdit>", '
84+ workbox_pattern = r'File "<Workbox(?:Selection)?>:(?P<workboxName>.*)", '
85+ line_pattern = r'line (?P<lineNum>\d{1,6})'
86+ in_str_pattern = r'(?P<inStr>, in)?'
87+
88+ # Put the pattern pieces to together to make patterns
89+ workbox_pattern = workbox_pattern + line_pattern + in_str_pattern
90+ cls .workbox_pattern = re .compile (workbox_pattern )
91+
92+ console_pattern = console_pattern + line_pattern + in_str_pattern
93+ cls .console_pattern = re .compile (console_pattern )
94+
95+ # Define a pattern to capture info from tracebacks. The newline/$ section
96+ # handle SyntaxError output that does not include the `, in ...` portion.
97+ pattern = r'File "(?P<filename>.*)", line (?P<lineNum>\d{1,10})(, in|\r\n|\n|$)'
98+ cls .traceback_pattern = re .compile (pattern )
99+
83100 def add_separator (self ):
84101 """Add a marker line for visual separation of console output."""
85102 # Ensure the input is written to the end of the document on a new line
@@ -624,9 +641,17 @@ def _write(self, msg, stream_type=StreamType.STDOUT):
624641 msg = "{}{}{}" .format (msg , indent , workboxLine )
625642
626643 elif isConsolePrEdit :
627- consoleLine = self .consoleLine
628- indent = self .getIndentForCodeTracebackLine (msg )
629- msg = "{}{}{}\n " .format (msg , indent , consoleLine )
644+ # Syntax error tracebacks are different than other Exception.
645+ # They don't include ", in ..." and are issued differently than
646+ # other Exceptions, in that they will issue the final piece of
647+ # offending code, whereas other Exceptions do not, for some
648+ # reason. They do not need, and shouldn't, be handled here.
649+ match = self .console_pattern .search (msg )
650+ inStr = match .groupdict ().get ("inStr" , "" )
651+ if inStr :
652+ consoleLine = self .consoleLine
653+ indent = self .getIndentForCodeTracebackLine (msg )
654+ msg = "{}{}{}\n " .format (msg , indent , consoleLine )
630655
631656 # To make it easier to see relevant lines of a traceback, optionally insert
632657 # a newline separating internal PrEditor code from the code run by user.
@@ -720,3 +745,7 @@ def _write(self, msg, stream_type=StreamType.STDOUT):
720745 """Should this console print captured exceptions? Only use this if
721746 stream_echo_stderr is disabled or you likely will get duplicate output.
722747 """
748+
749+
750+ # Build and add the class properties for regex patterns so subclasses can use them.
751+ ConsoleBase ._ConsoleBase__defineRegexPatterns ()
0 commit comments