mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-11-03 21:24:29 +00:00 
			
		
		
		
	[pyupgrade] Fix UP030 to avoid modifying double curly braces in format strings (#19378)
				
					
				
			## Summary Fixes #19348 --------- Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
This commit is contained in:
		
							parent
							
								
									f7c6a6b2d0
								
							
						
					
					
						commit
						d449c541cb
					
				
					 3 changed files with 62 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -124,10 +124,20 @@ fn is_sequential(indices: &[usize]) -> bool {
 | 
			
		|||
    indices.iter().enumerate().all(|(idx, value)| idx == *value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An opening curly brace, followed by any integer, followed by any text,
 | 
			
		||||
// followed by a closing brace.
 | 
			
		||||
static FORMAT_SPECIFIER: LazyLock<Regex> =
 | 
			
		||||
    LazyLock::new(|| Regex::new(r"\{(?P<int>\d+)(?P<fmt>.*?)}").unwrap());
 | 
			
		||||
static FORMAT_SPECIFIER: LazyLock<Regex> = LazyLock::new(|| {
 | 
			
		||||
    Regex::new(
 | 
			
		||||
        r"(?x)
 | 
			
		||||
            (?P<prefix>
 | 
			
		||||
                ^|[^{]|(?:\{{2})+  # preceded by nothing, a non-brace, or an even number of braces
 | 
			
		||||
            )
 | 
			
		||||
            \{                     # opening curly brace
 | 
			
		||||
                (?P<int>\d+)       # followed by any integer
 | 
			
		||||
                (?P<fmt>.*?)       # followed by any text
 | 
			
		||||
            }                      # followed by a closing brace
 | 
			
		||||
        ",
 | 
			
		||||
    )
 | 
			
		||||
    .unwrap()
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/// Remove the explicit positional indices from a format string.
 | 
			
		||||
fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a typed_arena::Arena<String>) {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +145,7 @@ fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a typed_arena::Are
 | 
			
		|||
        Expression::SimpleString(expr) => {
 | 
			
		||||
            expr.value = arena.alloc(
 | 
			
		||||
                FORMAT_SPECIFIER
 | 
			
		||||
                    .replace_all(expr.value, "{$fmt}")
 | 
			
		||||
                    .replace_all(expr.value, "$prefix{$fmt}")
 | 
			
		||||
                    .to_string(),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +156,7 @@ fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a typed_arena::Are
 | 
			
		|||
                    libcst_native::String::Simple(string) => {
 | 
			
		||||
                        string.value = arena.alloc(
 | 
			
		||||
                            FORMAT_SPECIFIER
 | 
			
		||||
                                .replace_all(string.value, "{$fmt}")
 | 
			
		||||
                                .replace_all(string.value, "$prefix{$fmt}")
 | 
			
		||||
                                .to_string(),
 | 
			
		||||
                        );
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -481,6 +481,7 @@ UP030_0.py:59:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		|||
   59 |+"{}_{}".format(2, 1, )
 | 
			
		||||
60 60 | 
 | 
			
		||||
61 61 | "{1}_{0}".format(1, 2)
 | 
			
		||||
62 62 | 
 | 
			
		||||
 | 
			
		||||
UP030_0.py:61:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		||||
   |
 | 
			
		||||
| 
						 | 
				
			
			@ -488,6 +489,8 @@ UP030_0.py:61:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		|||
60 |
 | 
			
		||||
61 | "{1}_{0}".format(1, 2)
 | 
			
		||||
   | ^^^^^^^^^^^^^^^^^^^^^^ UP030
 | 
			
		||||
62 |
 | 
			
		||||
63 | r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
   |
 | 
			
		||||
   = help: Remove explicit positional indices
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -497,3 +500,42 @@ UP030_0.py:61:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		|||
60 60 | 
 | 
			
		||||
61    |-"{1}_{0}".format(1, 2)
 | 
			
		||||
   61 |+"{}_{}".format(2, 1)
 | 
			
		||||
62 62 | 
 | 
			
		||||
63 63 | r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
64 64 | 
 | 
			
		||||
 | 
			
		||||
UP030_0.py:63:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		||||
   |
 | 
			
		||||
61 | "{1}_{0}".format(1, 2)
 | 
			
		||||
62 |
 | 
			
		||||
63 | r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP030
 | 
			
		||||
64 |
 | 
			
		||||
65 | "{{{0}}}".format(123)
 | 
			
		||||
   |
 | 
			
		||||
   = help: Remove explicit positional indices
 | 
			
		||||
 | 
			
		||||
ℹ Unsafe fix
 | 
			
		||||
60 60 | 
 | 
			
		||||
61 61 | "{1}_{0}".format(1, 2)
 | 
			
		||||
62 62 | 
 | 
			
		||||
63    |-r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
   63 |+r"\d{{1,2}} {}".format(42)
 | 
			
		||||
64 64 | 
 | 
			
		||||
65 65 | "{{{0}}}".format(123)
 | 
			
		||||
 | 
			
		||||
UP030_0.py:65:1: UP030 [*] Use implicit references for positional format fields
 | 
			
		||||
   |
 | 
			
		||||
63 | r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
64 |
 | 
			
		||||
65 | "{{{0}}}".format(123)
 | 
			
		||||
   | ^^^^^^^^^^^^^^^^^^^^^ UP030
 | 
			
		||||
   |
 | 
			
		||||
   = help: Remove explicit positional indices
 | 
			
		||||
 | 
			
		||||
ℹ Unsafe fix
 | 
			
		||||
62 62 | 
 | 
			
		||||
63 63 | r"\d{{1,2}} {0}".format(42)
 | 
			
		||||
64 64 | 
 | 
			
		||||
65    |-"{{{0}}}".format(123)
 | 
			
		||||
   65 |+"{{{}}}".format(123)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue