mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	gh-125331: Allow the parser to activate future imports on the fly (#125482)
This commit is contained in:
		
							parent
							
								
									05e89c34bd
								
							
						
					
					
						commit
						3bd3e09588
					
				
					 6 changed files with 50 additions and 2 deletions
				
			
		|  | @ -207,7 +207,7 @@ import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) } | |||
| # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS | ||||
| import_from[stmt_ty]: | ||||
|     | 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets { | ||||
|         _PyAST_ImportFrom(b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) } | ||||
|         _PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) } | ||||
|     | 'from' a=('.' | '...')+ 'import' b=import_from_targets { | ||||
|         _PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) } | ||||
| import_from_targets[asdl_alias_seq*]: | ||||
|  |  | |||
|  | @ -34,6 +34,32 @@ def test_guido_as_bdfl(self): | |||
|         # parser reports the start of the token | ||||
|         self.assertEqual(cm.exception.offset, 3) | ||||
| 
 | ||||
|     def test_barry_as_bdfl_look_ma_with_no_compiler_flags(self): | ||||
|         # Check that the future import is handled by the parser | ||||
|         # even if the compiler flags are not passed. | ||||
|         code = "from __future__ import barry_as_FLUFL;2 {0} 3" | ||||
|         compile(code.format('<>'), '<BDFL test>', 'exec') | ||||
|         with self.assertRaises(SyntaxError) as cm: | ||||
|             compile(code.format('!='), '<FLUFL test>', 'exec') | ||||
|         self.assertRegex(str(cm.exception), "with Barry as BDFL, use '<>' instead of '!='") | ||||
|         self.assertIn('2 != 3', cm.exception.text) | ||||
|         self.assertEqual(cm.exception.filename, '<FLUFL test>') | ||||
|         self.assertEqual(cm.exception.lineno, 1) | ||||
|         self.assertEqual(cm.exception.offset, len(code) - 4) | ||||
| 
 | ||||
|     def test_barry_as_bdfl_relative_import(self): | ||||
|         code = "from .__future__ import barry_as_FLUFL;2 {0} 3" | ||||
|         compile(code.format('!='), '<FLUFL test>', 'exec') | ||||
|         with self.assertRaises(SyntaxError) as cm: | ||||
|             compile(code.format('<>'), '<BDFL test>', 'exec') | ||||
|         self.assertRegex(str(cm.exception), "<BDFL test>") | ||||
|         self.assertIn('2 <> 3', cm.exception.text) | ||||
|         self.assertEqual(cm.exception.filename, '<BDFL test>') | ||||
|         self.assertEqual(cm.exception.lineno, 1) | ||||
|         self.assertEqual(cm.exception.offset, len(code) - 4) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -0,0 +1,5 @@ | |||
| ``from __future__ import barry_as_FLUFL`` now works in more contexts, | ||||
| including when it is used in files, with the ``-c`` flag, and in the REPL | ||||
| when there are multiple statements on the same line. Previously, it worked | ||||
| only on subsequent lines in the REPL, and when the appropriate flags were | ||||
| passed directly to :func:`compile`. Patch by Pablo Galindo. | ||||
|  | @ -1694,3 +1694,18 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings, | |||
|     assert(current_pos == n_elements); | ||||
|     return _PyAST_JoinedStr(values, lineno, col_offset, end_lineno, end_col_offset, p->arena); | ||||
| } | ||||
| 
 | ||||
| stmt_ty | ||||
| _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level, | ||||
|                   			   int lineno, int col_offset, int end_lineno, int end_col_offset, | ||||
|                       		   PyArena *arena) { | ||||
|     if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) { | ||||
|         for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) { | ||||
|             alias_ty alias = asdl_seq_GET(names, i); | ||||
|             if (PyUnicode_CompareWithASCIIString(alias->name, "barry_as_FLUFL") == 0) { | ||||
|                 p->flags |= PyPARSE_BARRY_AS_BDFL; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return _PyAST_ImportFrom(module, names, level, lineno, col_offset, end_lineno, end_col_offset, arena); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										2
									
								
								Parser/parser.c
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Parser/parser.c
									
										
									
										generated
									
									
									
								
							|  | @ -3360,7 +3360,7 @@ import_from_rule(Parser *p) | |||
|             UNUSED(_end_lineno); // Only used by EXTRA macro
 | ||||
|             int _end_col_offset = _token->end_col_offset; | ||||
|             UNUSED(_end_col_offset); // Only used by EXTRA macro
 | ||||
|             _res = _PyAST_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); | ||||
|             _res = _PyPegen_checked_future_import ( p , b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); | ||||
|             if (_res == NULL && PyErr_Occurred()) { | ||||
|                 p->error_indicator = 1; | ||||
|                 p->level--; | ||||
|  |  | |||
|  | @ -346,6 +346,8 @@ mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *); | |||
| void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); | ||||
| expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension); | ||||
| void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions); | ||||
| stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *, | ||||
|                                        int , int, int , int , int , PyArena *); | ||||
| 
 | ||||
| // Parser API
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Pablo Galindo Salgado
						Pablo Galindo Salgado