mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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] | ||||
|         self.can_colorize = _colorize.can_colorize() | ||||
| 
 | ||||
|     def showsyntaxerror(self, filename=None): | ||||
|         super().showsyntaxerror(colorize=self.can_colorize) | ||||
|     def showsyntaxerror(self, filename=None, **kwargs): | ||||
|         super().showsyntaxerror(colorize=self.can_colorize, **kwargs) | ||||
| 
 | ||||
|     def showtraceback(self): | ||||
|         super().showtraceback(colorize=self.can_colorize) | ||||
|  | @ -171,7 +171,7 @@ def runsource(self, source, filename="<input>", symbol="single"): | |||
|         try: | ||||
|             tree = ast.parse(source) | ||||
|         except (SyntaxError, OverflowError, ValueError): | ||||
|             self.showsyntaxerror(filename) | ||||
|             self.showsyntaxerror(filename, source=source) | ||||
|             return False | ||||
|         if 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" top-level 'await' and run background asyncio tasks." | ||||
|                     ) | ||||
|                 self.showsyntaxerror(filename) | ||||
|                 self.showsyntaxerror(filename, source=source) | ||||
|                 return False | ||||
|             except (OverflowError, ValueError): | ||||
|                 self.showsyntaxerror(filename) | ||||
|                 self.showsyntaxerror(filename, source=source) | ||||
|                 return False | ||||
| 
 | ||||
|             if code is None: | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ def runsource(self, source, filename="<input>", symbol="single"): | |||
|             code = self.compile(source, filename, symbol) | ||||
|         except (OverflowError, SyntaxError, ValueError): | ||||
|             # Case 1 | ||||
|             self.showsyntaxerror(filename) | ||||
|             self.showsyntaxerror(filename, source=source) | ||||
|             return False | ||||
| 
 | ||||
|         if code is None: | ||||
|  | @ -123,6 +123,12 @@ def showsyntaxerror(self, filename=None, **kwargs): | |||
|                 # Stuff in the right filename | ||||
|                 value = SyntaxError(msg, (filename, lineno, offset, line)) | ||||
|                 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__: | ||||
|             lines = traceback.format_exception_only(type, value, colorize=colorize) | ||||
|             self.write(''.join(lines)) | ||||
|  |  | |||
|  | @ -706,7 +706,7 @@ def prepend_syspath(self, filename): | |||
|             del _filename, _sys, _dirname, _dir | ||||
|             \n""".format(filename)) | ||||
| 
 | ||||
|     def showsyntaxerror(self, filename=None): | ||||
|     def showsyntaxerror(self, filename=None, **kwargs): | ||||
|         """Override Interactive Interpreter method: Use Colorizing | ||||
| 
 | ||||
|         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.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): | ||||
|         console = InteractiveColoredConsole() | ||||
|         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
	
	 Sergey B Kirpichev
						Sergey B Kirpichev