mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	[3.13] gh-121804: Always show error location for SyntaxError's in new repl (GH-121886) (#123148)
(cherry picked from commit 354d55eb1f)
			
			
This commit is contained in:
		
							parent
							
								
									21399a0963
								
							
						
					
					
						commit
						c8f4069ab1
					
				
					 5 changed files with 29 additions and 7 deletions
				
			
		| 
						 | 
					@ -161,8 +161,8 @@ def __init__(
 | 
				
			||||||
        super().__init__(locals=locals, filename=filename, local_exit=local_exit)  # type: ignore[call-arg]
 | 
					        super().__init__(locals=locals, filename=filename, local_exit=local_exit)  # type: ignore[call-arg]
 | 
				
			||||||
        self.can_colorize = _colorize.can_colorize()
 | 
					        self.can_colorize = _colorize.can_colorize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def showsyntaxerror(self, filename=None):
 | 
					    def showsyntaxerror(self, filename=None, **kwargs):
 | 
				
			||||||
        super().showsyntaxerror(colorize=self.can_colorize)
 | 
					        super().showsyntaxerror(colorize=self.can_colorize, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def showtraceback(self):
 | 
					    def showtraceback(self):
 | 
				
			||||||
        super().showtraceback(colorize=self.can_colorize)
 | 
					        super().showtraceback(colorize=self.can_colorize)
 | 
				
			||||||
| 
						 | 
					@ -171,7 +171,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            tree = ast.parse(source)
 | 
					            tree = ast.parse(source)
 | 
				
			||||||
        except (SyntaxError, OverflowError, ValueError):
 | 
					        except (SyntaxError, OverflowError, ValueError):
 | 
				
			||||||
            self.showsyntaxerror(filename)
 | 
					            self.showsyntaxerror(filename, source=source)
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
        if tree.body:
 | 
					        if tree.body:
 | 
				
			||||||
            *_, last_stmt = tree.body
 | 
					            *_, last_stmt = tree.body
 | 
				
			||||||
| 
						 | 
					@ -188,10 +188,10 @@ def runsource(self, source, filename="<input>", symbol="single"):
 | 
				
			||||||
                        f"Try the asyncio REPL ({python} -m asyncio) to use"
 | 
					                        f"Try the asyncio REPL ({python} -m asyncio) to use"
 | 
				
			||||||
                        f" top-level 'await' and run background asyncio tasks."
 | 
					                        f" top-level 'await' and run background asyncio tasks."
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                self.showsyntaxerror(filename)
 | 
					                self.showsyntaxerror(filename, source=source)
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
            except (OverflowError, ValueError):
 | 
					            except (OverflowError, ValueError):
 | 
				
			||||||
                self.showsyntaxerror(filename)
 | 
					                self.showsyntaxerror(filename, source=source)
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if code is None:
 | 
					            if code is None:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
 | 
				
			||||||
            code = self.compile(source, filename, symbol)
 | 
					            code = self.compile(source, filename, symbol)
 | 
				
			||||||
        except (OverflowError, SyntaxError, ValueError):
 | 
					        except (OverflowError, SyntaxError, ValueError):
 | 
				
			||||||
            # Case 1
 | 
					            # Case 1
 | 
				
			||||||
            self.showsyntaxerror(filename)
 | 
					            self.showsyntaxerror(filename, source=source)
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if code is None:
 | 
					        if code is None:
 | 
				
			||||||
| 
						 | 
					@ -123,6 +123,12 @@ def showsyntaxerror(self, filename=None, **kwargs):
 | 
				
			||||||
                # Stuff in the right filename
 | 
					                # Stuff in the right filename
 | 
				
			||||||
                value = SyntaxError(msg, (filename, lineno, offset, line))
 | 
					                value = SyntaxError(msg, (filename, lineno, offset, line))
 | 
				
			||||||
                sys.last_exc = sys.last_value = value
 | 
					                sys.last_exc = sys.last_value = value
 | 
				
			||||||
 | 
					        # Set the line of text that the exception refers to
 | 
				
			||||||
 | 
					        source = kwargs.pop('source', '')
 | 
				
			||||||
 | 
					        lines = source.splitlines()
 | 
				
			||||||
 | 
					        if (source and type is SyntaxError
 | 
				
			||||||
 | 
					                and not value.text and len(lines) >= value.lineno):
 | 
				
			||||||
 | 
					            value.text = lines[value.lineno - 1]
 | 
				
			||||||
        if sys.excepthook is sys.__excepthook__:
 | 
					        if sys.excepthook is sys.__excepthook__:
 | 
				
			||||||
            lines = traceback.format_exception_only(type, value, colorize=colorize)
 | 
					            lines = traceback.format_exception_only(type, value, colorize=colorize)
 | 
				
			||||||
            self.write(''.join(lines))
 | 
					            self.write(''.join(lines))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -706,7 +706,7 @@ def prepend_syspath(self, filename):
 | 
				
			||||||
            del _filename, _sys, _dirname, _dir
 | 
					            del _filename, _sys, _dirname, _dir
 | 
				
			||||||
            \n""".format(filename))
 | 
					            \n""".format(filename))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def showsyntaxerror(self, filename=None):
 | 
					    def showsyntaxerror(self, filename=None, **kwargs):
 | 
				
			||||||
        """Override Interactive Interpreter method: Use Colorizing
 | 
					        """Override Interactive Interpreter method: Use Colorizing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Color the offending position instead of printing it and pointing at it
 | 
					        Color the offending position instead of printing it and pointing at it
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,6 +88,20 @@ def test_runsource_returns_false_for_failed_compilation(self):
 | 
				
			||||||
        self.assertFalse(result)
 | 
					        self.assertFalse(result)
 | 
				
			||||||
        self.assertIn('SyntaxError', f.getvalue())
 | 
					        self.assertIn('SyntaxError', f.getvalue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @force_not_colorized
 | 
				
			||||||
 | 
					    def test_runsource_show_syntax_error_location(self):
 | 
				
			||||||
 | 
					        console = InteractiveColoredConsole()
 | 
				
			||||||
 | 
					        source = "def f(x, x): ..."
 | 
				
			||||||
 | 
					        f = io.StringIO()
 | 
				
			||||||
 | 
					        with contextlib.redirect_stderr(f):
 | 
				
			||||||
 | 
					            result = console.runsource(source)
 | 
				
			||||||
 | 
					        self.assertFalse(result)
 | 
				
			||||||
 | 
					        r = """
 | 
				
			||||||
 | 
					    def f(x, x): ...
 | 
				
			||||||
 | 
					             ^
 | 
				
			||||||
 | 
					SyntaxError: duplicate argument 'x' in function definition"""
 | 
				
			||||||
 | 
					        self.assertIn(r, f.getvalue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_runsource_shows_syntax_error_for_failed_compilation(self):
 | 
					    def test_runsource_shows_syntax_error_for_failed_compilation(self):
 | 
				
			||||||
        console = InteractiveColoredConsole()
 | 
					        console = InteractiveColoredConsole()
 | 
				
			||||||
        source = "print('Hello, world!'"
 | 
					        source = "print('Hello, world!'"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Correctly show error locations, when :exc:`SyntaxError` raised in new repl.
 | 
				
			||||||
 | 
					Patch by Sergey B Kirpichev.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue