mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 20:07:51 +00:00 
			
		
		
		
	Respect Q00* ignores in flake8-quotes rules (#10728)
				
					
				
			## Summary We lost the per-rule ignores when these were migrated to the AST, so if _any_ `Q` rule is enabled, they're now all enabled. Closes https://github.com/astral-sh/ruff/issues/10724. ## Test Plan Ran: ```shell ruff check . --isolated --select Q --ignore Q000 ruff check . --isolated --select Q --ignore Q001 ruff check . --isolated --select Q --ignore Q002 ruff check . --isolated --select Q --ignore Q000,Q001 ruff check . --isolated --select Q --ignore Q000,Q002 ruff check . --isolated --select Q --ignore Q001,Q002 ``` ...against: ```python ''' bad docsting ''' a = 'single' b = ''' bad multi line ''' ```
This commit is contained in:
		
							parent
							
								
									d36f60999d
								
							
						
					
					
						commit
						7b48443624
					
				
					 6 changed files with 146 additions and 3 deletions
				
			
		
							
								
								
									
										7
									
								
								crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | """This is a docstring.""" | ||||||
|  | 
 | ||||||
|  | this_is_an_inline_string = "double quote string" | ||||||
|  | 
 | ||||||
|  | this_is_a_multiline_string = """ | ||||||
|  | double quote string | ||||||
|  | """ | ||||||
|  | @ -195,4 +195,61 @@ mod tests { | ||||||
|         assert_messages!(snapshot, diagnostics); |         assert_messages!(snapshot, diagnostics); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test_case(Path::new("doubles_all.py"))] | ||||||
|  |     fn only_inline(path: &Path) -> Result<()> { | ||||||
|  |         let snapshot = format!("only_inline_{}", path.to_string_lossy()); | ||||||
|  |         let diagnostics = test_path( | ||||||
|  |             Path::new("flake8_quotes").join(path).as_path(), | ||||||
|  |             &LinterSettings { | ||||||
|  |                 flake8_quotes: super::settings::Settings { | ||||||
|  |                     inline_quotes: Quote::Single, | ||||||
|  |                     multiline_quotes: Quote::Single, | ||||||
|  |                     docstring_quotes: Quote::Single, | ||||||
|  |                     avoid_escape: true, | ||||||
|  |                 }, | ||||||
|  |                 ..LinterSettings::for_rules(vec![Rule::BadQuotesInlineString]) | ||||||
|  |             }, | ||||||
|  |         )?; | ||||||
|  |         assert_messages!(snapshot, diagnostics); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test_case(Path::new("doubles_all.py"))] | ||||||
|  |     fn only_multiline(path: &Path) -> Result<()> { | ||||||
|  |         let snapshot = format!("only_multiline_{}", path.to_string_lossy()); | ||||||
|  |         let diagnostics = test_path( | ||||||
|  |             Path::new("flake8_quotes").join(path).as_path(), | ||||||
|  |             &LinterSettings { | ||||||
|  |                 flake8_quotes: super::settings::Settings { | ||||||
|  |                     inline_quotes: Quote::Single, | ||||||
|  |                     multiline_quotes: Quote::Single, | ||||||
|  |                     docstring_quotes: Quote::Single, | ||||||
|  |                     avoid_escape: true, | ||||||
|  |                 }, | ||||||
|  |                 ..LinterSettings::for_rules(vec![Rule::BadQuotesMultilineString]) | ||||||
|  |             }, | ||||||
|  |         )?; | ||||||
|  |         assert_messages!(snapshot, diagnostics); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test_case(Path::new("doubles_all.py"))] | ||||||
|  |     fn only_docstring(path: &Path) -> Result<()> { | ||||||
|  |         let snapshot = format!("only_docstring_{}", path.to_string_lossy()); | ||||||
|  |         let diagnostics = test_path( | ||||||
|  |             Path::new("flake8_quotes").join(path).as_path(), | ||||||
|  |             &LinterSettings { | ||||||
|  |                 flake8_quotes: super::settings::Settings { | ||||||
|  |                     inline_quotes: Quote::Single, | ||||||
|  |                     multiline_quotes: Quote::Single, | ||||||
|  |                     docstring_quotes: Quote::Single, | ||||||
|  |                     avoid_escape: true, | ||||||
|  |                 }, | ||||||
|  |                 ..LinterSettings::for_rules(vec![Rule::BadQuotesDocstring]) | ||||||
|  |             }, | ||||||
|  |         )?; | ||||||
|  |         assert_messages!(snapshot, diagnostics); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ use ruff_source_file::Locator; | ||||||
| use ruff_text_size::{Ranged, TextRange}; | use ruff_text_size::{Ranged, TextRange}; | ||||||
| 
 | 
 | ||||||
| use crate::checkers::ast::Checker; | use crate::checkers::ast::Checker; | ||||||
|  | use crate::registry::Rule; | ||||||
| 
 | 
 | ||||||
| use super::super::settings::Quote; | use super::super::settings::Quote; | ||||||
| 
 | 
 | ||||||
|  | @ -334,6 +335,11 @@ fn strings(checker: &mut Checker, sequence: &[TextRange]) { | ||||||
| 
 | 
 | ||||||
|     for (range, trivia) in sequence.iter().zip(trivia) { |     for (range, trivia) in sequence.iter().zip(trivia) { | ||||||
|         if trivia.is_multiline { |         if trivia.is_multiline { | ||||||
|  |             // If multiline strings aren't enforced, ignore it.
 | ||||||
|  |             if !checker.enabled(Rule::BadQuotesMultilineString) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             // If our string is or contains a known good string, ignore it.
 |             // If our string is or contains a known good string, ignore it.
 | ||||||
|             if trivia |             if trivia | ||||||
|                 .raw_text |                 .raw_text | ||||||
|  | @ -375,6 +381,11 @@ fn strings(checker: &mut Checker, sequence: &[TextRange]) { | ||||||
|             // If we're not using the preferred type, only allow use to avoid escapes.
 |             // If we're not using the preferred type, only allow use to avoid escapes.
 | ||||||
|             && !relax_quote |             && !relax_quote | ||||||
|         { |         { | ||||||
|  |             // If inline strings aren't enforced, ignore it.
 | ||||||
|  |             if !checker.enabled(Rule::BadQuotesInlineString) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             if trivia.has_empty_text() |             if trivia.has_empty_text() | ||||||
|                 && text_ends_at_quote(locator, *range, quotes_settings.inline_quotes) |                 && text_ends_at_quote(locator, *range, quotes_settings.inline_quotes) | ||||||
|             { |             { | ||||||
|  | @ -455,10 +466,14 @@ pub(crate) fn check_string_quotes(checker: &mut Checker, string_like: StringLike | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     if checker.semantic().in_docstring() { |     if checker.semantic().in_docstring() { | ||||||
|         for range in ranges { |         if checker.enabled(Rule::BadQuotesDocstring) { | ||||||
|             docstring(checker, range); |             for range in ranges { | ||||||
|  |                 docstring(checker, range); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         strings(checker, &ranges); |         if checker.any_enabled(&[Rule::BadQuotesInlineString, Rule::BadQuotesMultilineString]) { | ||||||
|  |             strings(checker, &ranges); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | --- | ||||||
|  | source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs | ||||||
|  | --- | ||||||
|  | doubles_all.py:1:1: Q002 [*] Double quote docstring found but single quotes preferred | ||||||
|  |   | | ||||||
|  | 1 | """This is a docstring.""" | ||||||
|  |   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Q002 | ||||||
|  | 2 |  | ||||||
|  | 3 | this_is_an_inline_string = "double quote string" | ||||||
|  |   | | ||||||
|  |   = help: Replace double quotes docstring with single quotes | ||||||
|  | 
 | ||||||
|  | ℹ Safe fix | ||||||
|  | 1   |-"""This is a docstring.""" | ||||||
|  |   1 |+'''This is a docstring.''' | ||||||
|  | 2 2 |  | ||||||
|  | 3 3 | this_is_an_inline_string = "double quote string" | ||||||
|  | 4 4 | | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | --- | ||||||
|  | source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs | ||||||
|  | --- | ||||||
|  | doubles_all.py:3:28: Q000 [*] Double quotes found but single quotes preferred | ||||||
|  |   | | ||||||
|  | 1 | """This is a docstring.""" | ||||||
|  | 2 |  | ||||||
|  | 3 | this_is_an_inline_string = "double quote string" | ||||||
|  |   |                            ^^^^^^^^^^^^^^^^^^^^^ Q000 | ||||||
|  | 4 |  | ||||||
|  | 5 | this_is_a_multiline_string = """ | ||||||
|  |   | | ||||||
|  |   = help: Replace double quotes with single quotes | ||||||
|  | 
 | ||||||
|  | ℹ Safe fix | ||||||
|  | 1 1 | """This is a docstring.""" | ||||||
|  | 2 2 |  | ||||||
|  | 3   |-this_is_an_inline_string = "double quote string" | ||||||
|  |   3 |+this_is_an_inline_string = 'double quote string' | ||||||
|  | 4 4 |  | ||||||
|  | 5 5 | this_is_a_multiline_string = """ | ||||||
|  | 6 6 | double quote string | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | --- | ||||||
|  | source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs | ||||||
|  | --- | ||||||
|  | doubles_all.py:5:30: Q001 [*] Double quote multiline found but single quotes preferred | ||||||
|  |   | | ||||||
|  | 3 |   this_is_an_inline_string = "double quote string" | ||||||
|  | 4 |    | ||||||
|  | 5 |   this_is_a_multiline_string = """ | ||||||
|  |   |  ______________________________^ | ||||||
|  | 6 | | double quote string | ||||||
|  | 7 | | """ | ||||||
|  |   | |___^ Q001 | ||||||
|  |   | | ||||||
|  |   = help: Replace double multiline quotes with single quotes | ||||||
|  | 
 | ||||||
|  | ℹ Safe fix | ||||||
|  | 2 2 |  | ||||||
|  | 3 3 | this_is_an_inline_string = "double quote string" | ||||||
|  | 4 4 |  | ||||||
|  | 5   |-this_is_a_multiline_string = """ | ||||||
|  |   5 |+this_is_a_multiline_string = ''' | ||||||
|  | 6 6 | double quote string | ||||||
|  | 7   |-""" | ||||||
|  |   7 |+''' | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Charlie Marsh
						Charlie Marsh