mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-29 19:17:12 +00:00 
			
		
		
		
	Use insta_cmd (#6737)
This commit is contained in:
		
							parent
							
								
									7ead2c17b1
								
							
						
					
					
						commit
						e02d76f070
					
				
					 6 changed files with 423 additions and 311 deletions
				
			
		|  | @ -70,7 +70,10 @@ wild = { version = "2" } | |||
| 
 | ||||
| [dev-dependencies] | ||||
| assert_cmd = { version = "2.0.8" } | ||||
| # Avoid writing colored snapshots when running tests from the terminal | ||||
| colored = { workspace = true, features = ["no-color"]} | ||||
| insta = { workspace = true, features = ["filters"] } | ||||
| insta-cmd = { version = "0.4.0" } | ||||
| tempfile = "3.6.0" | ||||
| ureq = { version = "2.6.2", features = [] } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,15 +1,15 @@ | |||
| #![cfg(not(target_family = "wasm"))] | ||||
| 
 | ||||
| use std::io::{ErrorKind, Read}; | ||||
| use std::io::{ErrorKind, Read, Write}; | ||||
| use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener, TcpStream}; | ||||
| use std::path::{Path, PathBuf}; | ||||
| use std::process::Stdio; | ||||
| use std::process::{Command, Stdio}; | ||||
| use std::thread::sleep; | ||||
| use std::time::Duration; | ||||
| use std::{fs, process, str}; | ||||
| 
 | ||||
| use anyhow::{anyhow, Context, Result}; | ||||
| use assert_cmd::Command; | ||||
| use anyhow::{anyhow, bail, Context, Result}; | ||||
| use insta_cmd::get_cargo_bin; | ||||
| use log::info; | ||||
| use walkdir::WalkDir; | ||||
| 
 | ||||
|  | @ -29,13 +29,14 @@ impl Blackd { | |||
|         // Get free TCP port to run on
 | ||||
|         let address = TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?.local_addr()?; | ||||
| 
 | ||||
|         let server = process::Command::new("blackd") | ||||
|             .args([ | ||||
|                 "--bind-host", | ||||
|                 &address.ip().to_string(), | ||||
|                 "--bind-port", | ||||
|                 &address.port().to_string(), | ||||
|             ]) | ||||
|         let args = [ | ||||
|             "--bind-host", | ||||
|             &address.ip().to_string(), | ||||
|             "--bind-port", | ||||
|             &address.port().to_string(), | ||||
|         ]; | ||||
|         let server = Command::new("blackd") | ||||
|             .args(args) | ||||
|             .stdout(Stdio::null()) | ||||
|             .stderr(Stdio::null()) | ||||
|             .spawn() | ||||
|  | @ -51,16 +52,16 @@ impl Blackd { | |||
|                 Err(e) => return Err(e.into()), | ||||
|                 Ok(_) => { | ||||
|                     info!("`blackd` ready"); | ||||
|                     break; | ||||
|                     return Ok(Self { | ||||
|                         address, | ||||
|                         server, | ||||
|                         client: ureq::agent(), | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Ok(Self { | ||||
|             address, | ||||
|             server, | ||||
|             client: ureq::agent(), | ||||
|         }) | ||||
|         bail!("blackd {:?} failed to start", args) | ||||
|     } | ||||
| 
 | ||||
|     /// Format given code with blackd.
 | ||||
|  | @ -104,34 +105,42 @@ fn run_test(path: &Path, blackd: &Blackd, ruff_args: &[&str]) -> Result<()> { | |||
|     let input = fs::read(path)?; | ||||
| 
 | ||||
|     // Step 1: Run `ruff` on the input.
 | ||||
|     let step_1 = &Command::cargo_bin(BIN_NAME)? | ||||
|     let mut step_1 = Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(ruff_args) | ||||
|         .write_stdin(input) | ||||
|         .assert() | ||||
|         .append_context("step", "running input through ruff"); | ||||
|     if !step_1.get_output().status.success() { | ||||
|         .stdin(Stdio::piped()) | ||||
|         .stdout(Stdio::piped()) | ||||
|         .spawn()?; | ||||
|     if let Some(mut stdin) = step_1.stdin.take() { | ||||
|         stdin.write_all(input.as_ref())?; | ||||
|     } | ||||
|     let step_1_output = step_1.wait_with_output()?; | ||||
|     if !step_1_output.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Running input through ruff failed:\n{}", | ||||
|             str::from_utf8(&step_1.get_output().stderr)? | ||||
|             str::from_utf8(&step_1_output.stderr)? | ||||
|         )); | ||||
|     } | ||||
|     let step_1_output = step_1.get_output().stdout.clone(); | ||||
| 
 | ||||
|     // Step 2: Run `blackd` on the input.
 | ||||
|     let step_2_output = blackd.check(&step_1_output)?; | ||||
|     let step_2_output = blackd.check(&step_1_output.stdout.clone())?; | ||||
| 
 | ||||
|     // Step 3: Re-run `ruff` on the input.
 | ||||
|     let step_3 = &Command::cargo_bin(BIN_NAME)? | ||||
|     let mut step_3 = Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(ruff_args) | ||||
|         .write_stdin(step_2_output.clone()) | ||||
|         .assert(); | ||||
|     if !step_3.get_output().status.success() { | ||||
|         .stdin(Stdio::piped()) | ||||
|         .stdout(Stdio::piped()) | ||||
|         .spawn()?; | ||||
|     if let Some(mut stdin) = step_3.stdin.take() { | ||||
|         stdin.write_all(step_2_output.as_ref())?; | ||||
|     } | ||||
|     let step_3_output = step_3.wait_with_output()?; | ||||
|     if !step_3_output.status.success() { | ||||
|         return Err(anyhow!( | ||||
|             "Running input through ruff after black failed:\n{}", | ||||
|             str::from_utf8(&step_3.get_output().stderr)? | ||||
|             str::from_utf8(&step_3_output.stderr)? | ||||
|         )); | ||||
|     } | ||||
|     let step_3_output = step_3.get_output().stdout.clone(); | ||||
|     let step_3_output = step_3_output.stdout.clone(); | ||||
| 
 | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&step_2_output), | ||||
|  | @ -177,11 +186,13 @@ fn test_ruff_black_compatibility() -> Result<()> { | |||
|         "--fix", | ||||
|         "--line-length", | ||||
|         "88", | ||||
|         "--select ALL", | ||||
|         "--select", | ||||
|         "ALL", | ||||
|         // Exclude ruff codes, specifically RUF100, because it causes differences that are not a
 | ||||
|         // problem. Ruff would add a `# noqa: W292`  after the first run, black introduces a
 | ||||
|         // newline, and ruff removes the `# noqa: W292` again.
 | ||||
|         "--ignore RUF", | ||||
|         "--ignore", | ||||
|         "RUF", | ||||
|     ]; | ||||
| 
 | ||||
|     for entry in paths { | ||||
|  |  | |||
|  | @ -8,14 +8,15 @@ use std::fs::Permissions; | |||
| use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; | ||||
| #[cfg(unix)] | ||||
| use std::path::Path; | ||||
| use std::process::Command; | ||||
| use std::str; | ||||
| 
 | ||||
| #[cfg(unix)] | ||||
| use anyhow::Context; | ||||
| use anyhow::Result; | ||||
| use assert_cmd::Command; | ||||
| #[cfg(unix)] | ||||
| use clap::Parser; | ||||
| use insta_cmd::{assert_cmd_snapshot, get_cargo_bin}; | ||||
| #[cfg(unix)] | ||||
| use path_absolutize::path_dedot; | ||||
| #[cfg(unix)] | ||||
|  | @ -27,315 +28,280 @@ use ruff_cli::args::Args; | |||
| use ruff_cli::run; | ||||
| 
 | ||||
| const BIN_NAME: &str = "ruff"; | ||||
| const STDIN_BASE_OPTIONS: &[&str] = &["--isolated", "--no-cache", "-", "--format", "text"]; | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_success() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     cmd.args(["-", "--format", "text", "--isolated"]) | ||||
|         .write_stdin("") | ||||
|         .assert() | ||||
|         .success(); | ||||
|     Ok(()) | ||||
| fn stdin_success() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .pass_stdin(""), @r###" | ||||
|     success: true | ||||
|     exit_code: 0 | ||||
|     ----- stdout ----- | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_error() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--isolated"]) | ||||
|         .write_stdin("import os\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"-:1:8: F401 [*] `os` imported but unused
 | ||||
| Found 1 error. | ||||
| [*] 1 potentially fixable with the --fix option. | ||||
| "#
 | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn stdin_error() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .pass_stdin("import os\n"), @r#" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     -:1:8: F401 [*] `os` imported but unused | ||||
|     Found 1 error. | ||||
|     [*] 1 potentially fixable with the --fix option. | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "#);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_filename() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args([ | ||||
|             "-", | ||||
|             "--format", | ||||
|             "text", | ||||
|             "--stdin-filename", | ||||
|             "F401.py", | ||||
|             "--isolated", | ||||
|         ]) | ||||
|         .write_stdin("import os\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"F401.py:1:8: F401 [*] `os` imported but unused
 | ||||
| Found 1 error. | ||||
| [*] 1 potentially fixable with the --fix option. | ||||
| "#
 | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn stdin_filename() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(["--stdin-filename", "F401.py"]) | ||||
|         .pass_stdin("import os\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     F401.py:1:8: F401 [*] `os` imported but unused | ||||
|     Found 1 error. | ||||
|     [*] 1 potentially fixable with the --fix option. | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_source_type() -> Result<()> { | ||||
|     // Raise `TCH` errors in `.py` files.
 | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args([ | ||||
|             "-", | ||||
|             "--format", | ||||
|             "text", | ||||
|             "--stdin-filename", | ||||
|             "TCH.py", | ||||
|             "--isolated", | ||||
|         ]) | ||||
|         .write_stdin("import os\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"TCH.py:1:8: F401 [*] `os` imported but unused
 | ||||
| Found 1 error. | ||||
| [*] 1 potentially fixable with the --fix option. | ||||
| "#
 | ||||
|     ); | ||||
| /// Raise `TCH` errors in `.py` files ...
 | ||||
| fn stdin_source_type_py() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(["--stdin-filename", "TCH.py"]) | ||||
|         .pass_stdin("import os\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     TCH.py:1:8: F401 [*] `os` imported but unused | ||||
|     Found 1 error. | ||||
|     [*] 1 potentially fixable with the --fix option. | ||||
| 
 | ||||
|     // But not in `.pyi` files.
 | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     cmd.args([ | ||||
|         "-", | ||||
|         "--format", | ||||
|         "text", | ||||
|         "--stdin-filename", | ||||
|         "TCH.pyi", | ||||
|         "--isolated", | ||||
|         "--select", | ||||
|         "TCH", | ||||
|     ]) | ||||
|     .write_stdin("import os\n") | ||||
|     .assert() | ||||
|     .success(); | ||||
|     Ok(()) | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| /// ... but not in `.pyi` files.
 | ||||
| #[test] | ||||
| fn stdin_source_type_pyi() { | ||||
|     let args = ["--stdin-filename", "TCH.pyi", "--select", "TCH"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("import os\n"), @r###" | ||||
|     success: true | ||||
|     exit_code: 0 | ||||
|     ----- stdout ----- | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[cfg(unix)] | ||||
| #[test] | ||||
| fn stdin_json() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args([ | ||||
|             "-", | ||||
|             "--format", | ||||
|             "json", | ||||
|             "--stdin-filename", | ||||
|             "F401.py", | ||||
|             "--isolated", | ||||
|         ]) | ||||
|         .write_stdin("import os\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
| fn stdin_json() { | ||||
|     let args = [ | ||||
|         "-", | ||||
|         "--isolated", | ||||
|         "--no-cache", | ||||
|         "--format", | ||||
|         "json", | ||||
|         "--stdin-filename", | ||||
|         "F401.py", | ||||
|     ]; | ||||
| 
 | ||||
|     let directory = path_dedot::CWD.to_str().unwrap(); | ||||
|     let binding = Path::new(directory).join("F401.py"); | ||||
|     let file_path = binding.display(); | ||||
| 
 | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         format!( | ||||
|             r#"[
 | ||||
|   {{ | ||||
|     "code": "F401", | ||||
|     "end_location": {{ | ||||
|       "column": 10, | ||||
|       "row": 1 | ||||
|     }}, | ||||
|     "filename": "{file_path}", | ||||
|     "fix": {{ | ||||
|       "applicability": "Automatic", | ||||
|       "edits": [ | ||||
|         {{ | ||||
|           "content": "", | ||||
|           "end_location": {{ | ||||
|             "column": 1, | ||||
|             "row": 2 | ||||
|           }}, | ||||
|           "location": {{ | ||||
|             "column": 1, | ||||
|             "row": 1 | ||||
|           }} | ||||
|         }} | ||||
|       ], | ||||
|       "message": "Remove unused import: `os`" | ||||
|     }}, | ||||
|     "location": {{ | ||||
|       "column": 8, | ||||
|       "row": 1 | ||||
|     }}, | ||||
|     "message": "`os` imported but unused", | ||||
|     "noqa_row": 1, | ||||
|     "url": "https://beta.ruff.rs/docs/rules/unused-import" | ||||
|   }} | ||||
| ]"#
 | ||||
|         ) | ||||
|     ); | ||||
|     Ok(()) | ||||
|     insta::with_settings!({filters => vec![ | ||||
|         (file_path.to_string().as_str(), "/path/to/F401.py"), | ||||
|     ]}, { | ||||
|         assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|             .args(args) | ||||
|             .pass_stdin("import os\n")); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_autofix() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--fix", "--isolated"]) | ||||
|         .write_stdin("import os\nimport sys\n\nprint(sys.version)\n") | ||||
|         .assert() | ||||
|         .success(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         "import sys\n\nprint(sys.version)\n" | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn stdin_autofix() { | ||||
|     let args = ["--fix"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("import os\nimport sys\n\nprint(sys.version)\n"), @r###" | ||||
|     success: true | ||||
|     exit_code: 0 | ||||
|     ----- stdout ----- | ||||
|     import sys | ||||
| 
 | ||||
|     print(sys.version) | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_autofix_when_not_fixable_should_still_print_contents() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--fix", "--isolated"]) | ||||
|         .write_stdin("import os\nimport sys\n\nif (1, 2):\n     print(sys.version)\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         "import sys\n\nif (1, 2):\n     print(sys.version)\n" | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn stdin_autofix_when_not_fixable_should_still_print_contents() { | ||||
|     let args = ["--fix"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("import os\nimport sys\n\nif (1, 2):\n     print(sys.version)\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     import sys | ||||
| 
 | ||||
|     if (1, 2): | ||||
|          print(sys.version) | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn stdin_autofix_when_no_issues_should_still_print_contents() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--fix", "--isolated"]) | ||||
|         .write_stdin("import sys\n\nprint(sys.version)\n") | ||||
|         .assert() | ||||
|         .success(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         "import sys\n\nprint(sys.version)\n" | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn stdin_autofix_when_no_issues_should_still_print_contents() { | ||||
|     let args = ["--fix"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("import sys\n\nprint(sys.version)\n"), @r###" | ||||
|     success: true | ||||
|     exit_code: 0 | ||||
|     ----- stdout ----- | ||||
|     import sys | ||||
| 
 | ||||
|     print(sys.version) | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn show_source() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--show-source", "--isolated"]) | ||||
|         .write_stdin("l = 1") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert!(str::from_utf8(&output.get_output().stdout)?.contains("l = 1")); | ||||
|     Ok(()) | ||||
| fn show_source() { | ||||
|     let args = ["--show-source"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("l = 1"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     -:1:1: E741 Ambiguous variable name: `l` | ||||
|       | | ||||
|     1 | l = 1 | ||||
|       | ^ E741 | ||||
|       | | ||||
| 
 | ||||
|     Found 1 error. | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn explain_status_codes() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     cmd.args(["--explain", "F401"]).assert().success(); | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     cmd.args(["--explain", "RUF404"]).assert().failure(); | ||||
|     Ok(()) | ||||
| fn explain_status_codes_f401() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).args(["--explain", "F401"])); | ||||
| } | ||||
| #[test] | ||||
| fn explain_status_codes_ruf404() { | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).args(["--explain", "RUF404"]), @r###" | ||||
|     success: false | ||||
|     exit_code: 2 | ||||
|     ----- stdout ----- | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     error: invalid value 'RUF404' for '[RULE]': unknown rule code | ||||
| 
 | ||||
|     For more information, try '--help'. | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn show_statistics() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|         .args([ | ||||
|             "-", | ||||
|             "--format", | ||||
|             "text", | ||||
|             "--select", | ||||
|             "F401", | ||||
|             "--statistics", | ||||
|             "--isolated", | ||||
|         ]) | ||||
|         .write_stdin("import sys\nimport os\n\nprint(os.getuid())\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)? | ||||
|             .lines() | ||||
|             .last() | ||||
|             .unwrap(), | ||||
|         "1\tF401\t[*] `sys` imported but unused" | ||||
|     ); | ||||
|     Ok(()) | ||||
| fn show_statistics() { | ||||
|     let args = ["--select", "F401", "--statistics"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("import sys\nimport os\n\nprint(os.getuid())\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     1	F401	[*] `sys` imported but unused | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn nursery_prefix() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
| 
 | ||||
| fn nursery_prefix() { | ||||
|     // `--select E` should detect E741, but not E225, which is in the nursery.
 | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--isolated", "--select", "E"]) | ||||
|         .write_stdin("I=42\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"-:1:1: E741 Ambiguous variable name: `I`
 | ||||
| Found 1 error. | ||||
| "#
 | ||||
|     ); | ||||
|     let args = ["--select", "E"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("I=42\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     -:1:1: E741 Ambiguous variable name: `I` | ||||
|     Found 1 error. | ||||
| 
 | ||||
|     Ok(()) | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn nursery_all() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
| 
 | ||||
| fn nursery_all() { | ||||
|     // `--select ALL` should detect E741, but not E225, which is in the nursery.
 | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--isolated", "--select", "E"]) | ||||
|         .write_stdin("I=42\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"-:1:1: E741 Ambiguous variable name: `I`
 | ||||
| Found 1 error. | ||||
| "#
 | ||||
|     ); | ||||
|     let args = ["--select", "ALL"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("I=42\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     -:1:1: E741 Ambiguous variable name: `I` | ||||
|     -:1:1: D100 Missing docstring in public module | ||||
|     Found 2 errors. | ||||
| 
 | ||||
|     Ok(()) | ||||
|     ----- stderr ----- | ||||
|     warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `one-blank-line-before-class`. | ||||
|     warning: `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. Ignoring `multi-line-summary-second-line`. | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn nursery_direct() -> Result<()> { | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
| 
 | ||||
| fn nursery_direct() { | ||||
|     // `--select E225` should detect E225.
 | ||||
|     let output = cmd | ||||
|         .args(["-", "--format", "text", "--isolated", "--select", "E225"]) | ||||
|         .write_stdin("I=42\n") | ||||
|         .assert() | ||||
|         .failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         r#"-:1:2: E225 Missing whitespace around operator
 | ||||
| Found 1 error. | ||||
| "#
 | ||||
|     ); | ||||
|     let args = ["--select", "E225"]; | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(STDIN_BASE_OPTIONS) | ||||
|         .args(args) | ||||
|         .pass_stdin("I=42\n"), @r###" | ||||
|     success: false | ||||
|     exit_code: 1 | ||||
|     ----- stdout ----- | ||||
|     -:1:2: E225 Missing whitespace around operator | ||||
|     Found 1 error. | ||||
| 
 | ||||
|     Ok(()) | ||||
|     ----- stderr ----- | ||||
|     "###);
 | ||||
| } | ||||
| 
 | ||||
| /// An unreadable pyproject.toml in non-isolated mode causes ruff to hard-error trying to build up
 | ||||
|  | @ -376,17 +342,17 @@ fn unreadable_dir() -> Result<()> { | |||
| 
 | ||||
|     // We (currently?) have to use a subcommand to check exit status (currently wrong) and logging
 | ||||
|     // output
 | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd | ||||
|     // TODO(konstin): This should be a failure, but we currently can't track that
 | ||||
|     assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|         .args(["--no-cache", "--isolated"]) | ||||
|         .arg(&unreadable_dir) | ||||
|         .assert() | ||||
|         // TODO(konstin): This should be a failure, but we currently can't track that
 | ||||
|         .success(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stderr)?, | ||||
|         "warning: Encountered error: Permission denied (os error 13)\n" | ||||
|     ); | ||||
|         .arg(&unreadable_dir), @r###" | ||||
|     success: true | ||||
|     exit_code: 0 | ||||
|     ----- stdout ----- | ||||
| 
 | ||||
|     ----- stderr ----- | ||||
|     warning: Encountered error: Permission denied (os error 13) | ||||
|     "###);
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
|  | @ -416,17 +382,22 @@ fn check_input_from_argfile() -> Result<()> { | |||
|         format!("@{}", &input_file_path.display()), | ||||
|     ]; | ||||
| 
 | ||||
|     let mut cmd = Command::cargo_bin(BIN_NAME)?; | ||||
|     let output = cmd.args(args).write_stdin("").assert().failure(); | ||||
|     assert_eq!( | ||||
|         str::from_utf8(&output.get_output().stdout)?, | ||||
|         format!( | ||||
|             "{}:1:8: F401 [*] `os` imported but unused
 | ||||
| Found 1 error. | ||||
| [*] 1 potentially fixable with the --fix option. | ||||
| ",
 | ||||
|             file_a_path.display() | ||||
|         ) | ||||
|     ); | ||||
|     insta::with_settings!({filters => vec![ | ||||
|         (file_a_path.display().to_string().as_str(), "/path/to/a.py"), | ||||
|     ]}, { | ||||
|         assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) | ||||
|             .args(args) | ||||
|             .pass_stdin(""), @r###" | ||||
|         success: false | ||||
|         exit_code: 1 | ||||
|         ----- stdout ----- | ||||
|         /path/to/a.py:1:8: F401 [*] `os` imported but unused | ||||
|         Found 1 error. | ||||
|         [*] 1 potentially fixable with the --fix option. | ||||
| 
 | ||||
|         ----- stderr ----- | ||||
|         "###);
 | ||||
|     }); | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,61 @@ | |||
| --- | ||||
| source: crates/ruff_cli/tests/integration_test.rs | ||||
| info: | ||||
|   program: ruff | ||||
|   args: | ||||
|     - "--explain" | ||||
|     - F401 | ||||
| --- | ||||
| success: true | ||||
| exit_code: 0 | ||||
| ----- stdout ----- | ||||
| # unused-import (F401) | ||||
| 
 | ||||
| Derived from the **Pyflakes** linter. | ||||
| 
 | ||||
| Autofix is sometimes available. | ||||
| 
 | ||||
| ## What it does | ||||
| Checks for unused imports. | ||||
| 
 | ||||
| ## Why is this bad? | ||||
| Unused imports add a performance overhead at runtime, and risk creating | ||||
| import cycles. They also increase the cognitive load of reading the code. | ||||
| 
 | ||||
| If an import statement is used to check for the availability or existence | ||||
| of a module, consider using `importlib.util.find_spec` instead. | ||||
| 
 | ||||
| ## Example | ||||
| ```python | ||||
| import numpy as np  # unused import | ||||
| 
 | ||||
| 
 | ||||
| def area(radius): | ||||
|     return 3.14 * radius**2 | ||||
| ``` | ||||
| 
 | ||||
| Use instead: | ||||
| ```python | ||||
| def area(radius): | ||||
|     return 3.14 * radius**2 | ||||
| ``` | ||||
| 
 | ||||
| To check the availability of a module, use `importlib.util.find_spec`: | ||||
| ```python | ||||
| from importlib.util import find_spec | ||||
| 
 | ||||
| if find_spec("numpy") is not None: | ||||
|     print("numpy is installed") | ||||
| else: | ||||
|     print("numpy is not installed") | ||||
| ``` | ||||
| 
 | ||||
| ## Options | ||||
| - `pyflakes.extend-generics` | ||||
| 
 | ||||
| ## References | ||||
| - [Python documentation: `import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement) | ||||
| - [Python documentation: `importlib.util.find_spec`](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec) | ||||
| 
 | ||||
| ----- stderr ----- | ||||
| 
 | ||||
|  | @ -0,0 +1,53 @@ | |||
| --- | ||||
| source: crates/ruff_cli/tests/integration_test.rs | ||||
| info: | ||||
|   program: ruff | ||||
|   args: | ||||
|     - "-" | ||||
|     - "--isolated" | ||||
|     - "--no-cache" | ||||
|     - "--format" | ||||
|     - json | ||||
|     - "--stdin-filename" | ||||
|     - F401.py | ||||
|   stdin: "import os\n" | ||||
| --- | ||||
| success: false | ||||
| exit_code: 1 | ||||
| ----- stdout ----- | ||||
| [ | ||||
|   { | ||||
|     "code": "F401", | ||||
|     "end_location": { | ||||
|       "column": 10, | ||||
|       "row": 1 | ||||
|     }, | ||||
|     "filename": "/path/to/F401.py", | ||||
|     "fix": { | ||||
|       "applicability": "Automatic", | ||||
|       "edits": [ | ||||
|         { | ||||
|           "content": "", | ||||
|           "end_location": { | ||||
|             "column": 1, | ||||
|             "row": 2 | ||||
|           }, | ||||
|           "location": { | ||||
|             "column": 1, | ||||
|             "row": 1 | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "message": "Remove unused import: `os`" | ||||
|     }, | ||||
|     "location": { | ||||
|       "column": 8, | ||||
|       "row": 1 | ||||
|     }, | ||||
|     "message": "`os` imported but unused", | ||||
|     "noqa_row": 1, | ||||
|     "url": "https://beta.ruff.rs/docs/rules/unused-import" | ||||
|   } | ||||
| ] | ||||
| ----- stderr ----- | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 konsti
						konsti