From 0923b327aa80a3ab8def2a003b8e208119f5acd4 Mon Sep 17 00:00:00 2001 From: harupy Date: Thu, 17 Aug 2023 08:25:28 +0900 Subject: [PATCH 1/4] Support glob patterns for raises_require_match_for and raises_require_match_for Signed-off-by: harupy --- .../fixtures/flake8_pytest_style/PT011.py | 7 ++ .../ruff/src/rules/flake8_pytest_style/mod.rs | 23 ++++- .../rules/flake8_pytest_style/rules/raises.rs | 14 ++- .../src/rules/flake8_pytest_style/settings.rs | 88 ++++++++++++++++--- ...e8_pytest_style__tests__PT011_default.snap | 46 +++++----- ..._tests__PT011_extend_broad_exceptions.snap | 54 ++++++------ ...8_pytest_style__tests__PT011_glob_all.snap | 73 +++++++++++++++ ...st_style__tests__PT011_glob_submodule.snap | 22 +++++ ...tests__PT011_replace_broad_exceptions.snap | 8 +- crates/ruff/src/settings/mod.rs | 3 +- 10 files changed, 263 insertions(+), 75 deletions(-) create mode 100644 crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap create mode 100644 crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap diff --git a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py index 70d877c60eb124..fbec3e2fa0aae2 100644 --- a/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py +++ b/crates/ruff/resources/test/fixtures/flake8_pytest_style/PT011.py @@ -1,3 +1,4 @@ +from pickle import PicklingError, UnpicklingError import socket import pytest @@ -20,6 +21,12 @@ def test_error_no_argument_given(): with pytest.raises(socket.error): raise ValueError("Can't divide 1 by 0") + with pytest.raises(PicklingError): + raise PicklingError("Can't pickle") + + with pytest.raises(UnpicklingError): + raise UnpicklingError("Can't unpickle") + def test_error_match_is_empty(): with pytest.raises(ValueError, match=None): diff --git a/crates/ruff/src/rules/flake8_pytest_style/mod.rs b/crates/ruff/src/rules/flake8_pytest_style/mod.rs index faa28606eba96b..cf3da03273a461 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/mod.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/mod.rs @@ -11,6 +11,7 @@ mod tests { use test_case::test_case; use crate::registry::Rule; + use crate::settings::types::IdentifierPattern; use crate::test::test_path; use crate::{assert_messages, settings}; @@ -143,7 +144,7 @@ mod tests { Rule::PytestRaisesTooBroad, Path::new("PT011.py"), Settings { - raises_extend_require_match_for: vec!["ZeroDivisionError".to_string()], + raises_extend_require_match_for: vec![IdentifierPattern::new("ZeroDivisionError").unwrap()], ..Settings::default() }, "PT011_extend_broad_exceptions" @@ -152,11 +153,29 @@ mod tests { Rule::PytestRaisesTooBroad, Path::new("PT011.py"), Settings { - raises_require_match_for: vec!["ZeroDivisionError".to_string()], + raises_require_match_for: vec![IdentifierPattern::new("ZeroDivisionError").unwrap()], ..Settings::default() }, "PT011_replace_broad_exceptions" )] + #[test_case( + Rule::PytestRaisesTooBroad, + Path::new("PT011.py"), + Settings { + raises_require_match_for: vec![IdentifierPattern::new("*").unwrap()], + ..Settings::default() + }, + "PT011_glob_all" + )] + #[test_case( + Rule::PytestRaisesTooBroad, + Path::new("PT011.py"), + Settings { + raises_require_match_for: vec![IdentifierPattern::new("pickle.*").unwrap()], + ..Settings::default() + }, + "PT011_glob_submodule" + )] #[test_case( Rule::PytestRaisesWithMultipleStatements, Path::new("PT012.py"), diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs index 759cba2659f37a..e3316f774fdc97 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs @@ -1,7 +1,7 @@ +use itertools::Itertools; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::format_call_path; -use ruff_python_ast::call_path::from_qualified_name; use ruff_python_ast::helpers::is_compound_statement; use ruff_python_ast::{self as ast, Expr, Ranged, Stmt, WithItem}; use ruff_python_semantic::SemanticModel; @@ -231,7 +231,7 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .semantic() .resolve_call_path(exception) .and_then(|call_path| { - let is_broad_exception = checker + checker .settings .flake8_pytest_style .raises_require_match_for @@ -242,12 +242,10 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .flake8_pytest_style .raises_extend_require_match_for, ) - .any(|target| call_path == from_qualified_name(target)); - if is_broad_exception { - Some(format_call_path(&call_path)) - } else { - None - } + .any(|pattern| { + pattern.matches(&call_path.iter().filter(|s| !s.is_empty()).join(".")) + }) + .then(|| format_call_path(&call_path)) }) { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_pytest_style/settings.rs b/crates/ruff/src/rules/flake8_pytest_style/settings.rs index d00a3d8ebcb1f9..bbbbebc86f501f 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/settings.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/settings.rs @@ -1,12 +1,15 @@ //! Settings for the `flake8-pytest-style` plugin. +use std::error::Error; +use std::fmt; use serde::{Deserialize, Serialize}; +use crate::settings::types::IdentifierPattern; use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions}; use super::types; -fn default_broad_exceptions() -> Vec { +fn default_broad_exceptions() -> Vec { [ "BaseException", "Exception", @@ -16,7 +19,7 @@ fn default_broad_exceptions() -> Vec { "EnvironmentError", "socket.error", ] - .map(ToString::to_string) + .map(|pattern| IdentifierPattern::new(pattern).expect("invalid default exception pattern")) .to_vec() } @@ -86,6 +89,9 @@ pub struct Options { )] /// List of exception names that require a match= parameter in a /// `pytest.raises()` call. + /// + /// Supports glob patterns. For more information on the glob syntax, refer + /// to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax). pub raises_require_match_for: Option>, #[option( default = "[]", @@ -100,6 +106,9 @@ pub struct Options { /// the entire list. /// Note that this option does not remove any exceptions from the default /// list. + /// + /// Supports glob patterns. For more information on the glob syntax, refer + /// to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax). pub raises_extend_require_match_for: Option>, #[option( default = "true", @@ -120,26 +129,44 @@ pub struct Settings { pub parametrize_names_type: types::ParametrizeNameType, pub parametrize_values_type: types::ParametrizeValuesType, pub parametrize_values_row_type: types::ParametrizeValuesRowType, - pub raises_require_match_for: Vec, - pub raises_extend_require_match_for: Vec, + pub raises_require_match_for: Vec, + pub raises_extend_require_match_for: Vec, pub mark_parentheses: bool, } -impl From for Settings { - fn from(options: Options) -> Self { - Self { +impl TryFrom for Settings { + type Error = SettingsError; + + fn try_from(options: Options) -> Result { + Ok(Self { fixture_parentheses: options.fixture_parentheses.unwrap_or(true), parametrize_names_type: options.parametrize_names_type.unwrap_or_default(), parametrize_values_type: options.parametrize_values_type.unwrap_or_default(), parametrize_values_row_type: options.parametrize_values_row_type.unwrap_or_default(), raises_require_match_for: options .raises_require_match_for + .map(|patterns| { + patterns + .into_iter() + .map(|pattern| IdentifierPattern::new(&pattern)) + .collect() + }) + .transpose() + .map_err(SettingsError::InvalidRaisesRequireMatchFor)? .unwrap_or_else(default_broad_exceptions), raises_extend_require_match_for: options .raises_extend_require_match_for + .map(|patterns| { + patterns + .into_iter() + .map(|pattern| IdentifierPattern::new(&pattern)) + .collect() + }) + .transpose() + .map_err(SettingsError::InvalidRaisesExtendRequireMatchFor)? .unwrap_or_default(), mark_parentheses: options.mark_parentheses.unwrap_or(true), - } + }) } } impl From for Options { @@ -149,8 +176,20 @@ impl From for Options { parametrize_names_type: Some(settings.parametrize_names_type), parametrize_values_type: Some(settings.parametrize_values_type), parametrize_values_row_type: Some(settings.parametrize_values_row_type), - raises_require_match_for: Some(settings.raises_require_match_for), - raises_extend_require_match_for: Some(settings.raises_extend_require_match_for), + raises_require_match_for: Some( + settings + .raises_require_match_for + .iter() + .map(ToString::to_string) + .collect(), + ), + raises_extend_require_match_for: Some( + settings + .raises_extend_require_match_for + .iter() + .map(ToString::to_string) + .collect(), + ), mark_parentheses: Some(settings.mark_parentheses), } } @@ -169,3 +208,32 @@ impl Default for Settings { } } } + +/// Error returned by the [`TryFrom`] implementation of [`Settings`]. +#[derive(Debug)] +pub enum SettingsError { + InvalidRaisesRequireMatchFor(glob::PatternError), + InvalidRaisesExtendRequireMatchFor(glob::PatternError), +} + +impl fmt::Display for SettingsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SettingsError::InvalidRaisesRequireMatchFor(err) => { + write!(f, "invalid raises-require-match-for pattern: {err}") + } + SettingsError::InvalidRaisesExtendRequireMatchFor(err) => { + write!(f, "invalid raises-extend-require-match-for pattern: {err}") + } + } + } +} + +impl Error for SettingsError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + SettingsError::InvalidRaisesRequireMatchFor(err) => Some(err), + SettingsError::InvalidRaisesExtendRequireMatchFor(err) => Some(err), + } + } +} diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap index 0715f78d5c5472..ca94e0c21291ae 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_default.snap @@ -1,47 +1,47 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:17:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -16 | def test_error_no_argument_given(): -17 | with pytest.raises(ValueError): +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): | ^^^^^^^^^^ PT011 -18 | raise ValueError("Can't divide 1 by 0") +19 | raise ValueError("Can't divide 1 by 0") | -PT011.py:20:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception | -18 | raise ValueError("Can't divide 1 by 0") -19 | -20 | with pytest.raises(socket.error): +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): | ^^^^^^^^^^^^ PT011 -21 | raise ValueError("Can't divide 1 by 0") +22 | raise ValueError("Can't divide 1 by 0") | -PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -24 | def test_error_match_is_empty(): -25 | with pytest.raises(ValueError, match=None): +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): | ^^^^^^^^^^ PT011 -26 | raise ValueError("Can't divide 1 by 0") +33 | raise ValueError("Can't divide 1 by 0") | -PT011.py:28:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -26 | raise ValueError("Can't divide 1 by 0") -27 | -28 | with pytest.raises(ValueError, match=""): +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): | ^^^^^^^^^^ PT011 -29 | raise ValueError("Can't divide 1 by 0") +36 | raise ValueError("Can't divide 1 by 0") | -PT011.py:31:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -29 | raise ValueError("Can't divide 1 by 0") -30 | -31 | with pytest.raises(ValueError, match=f""): +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): | ^^^^^^^^^^ PT011 -32 | raise ValueError("Can't divide 1 by 0") +39 | raise ValueError("Can't divide 1 by 0") | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap index f338e561587743..023618c278eed5 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_extend_broad_exceptions.snap @@ -1,55 +1,55 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:12:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception | -11 | def test_ok_different_error_from_config(): -12 | with pytest.raises(ZeroDivisionError): +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): | ^^^^^^^^^^^^^^^^^ PT011 -13 | raise ZeroDivisionError("Can't divide by 0") +14 | raise ZeroDivisionError("Can't divide by 0") | -PT011.py:17:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -16 | def test_error_no_argument_given(): -17 | with pytest.raises(ValueError): +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): | ^^^^^^^^^^ PT011 -18 | raise ValueError("Can't divide 1 by 0") +19 | raise ValueError("Can't divide 1 by 0") | -PT011.py:20:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception | -18 | raise ValueError("Can't divide 1 by 0") -19 | -20 | with pytest.raises(socket.error): +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): | ^^^^^^^^^^^^ PT011 -21 | raise ValueError("Can't divide 1 by 0") +22 | raise ValueError("Can't divide 1 by 0") | -PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -24 | def test_error_match_is_empty(): -25 | with pytest.raises(ValueError, match=None): +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): | ^^^^^^^^^^ PT011 -26 | raise ValueError("Can't divide 1 by 0") +33 | raise ValueError("Can't divide 1 by 0") | -PT011.py:28:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -26 | raise ValueError("Can't divide 1 by 0") -27 | -28 | with pytest.raises(ValueError, match=""): +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): | ^^^^^^^^^^ PT011 -29 | raise ValueError("Can't divide 1 by 0") +36 | raise ValueError("Can't divide 1 by 0") | -PT011.py:31:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception | -29 | raise ValueError("Can't divide 1 by 0") -30 | -31 | with pytest.raises(ValueError, match=f""): +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): | ^^^^^^^^^^ PT011 -32 | raise ValueError("Can't divide 1 by 0") +39 | raise ValueError("Can't divide 1 by 0") | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap new file mode 100644 index 00000000000000..f10518091d66cc --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_all.snap @@ -0,0 +1,73 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception + | +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): + | ^^^^^^^^^^^^^^^^^ PT011 +14 | raise ZeroDivisionError("Can't divide by 0") + | + +PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +17 | def test_error_no_argument_given(): +18 | with pytest.raises(ValueError): + | ^^^^^^^^^^ PT011 +19 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception + | +19 | raise ValueError("Can't divide 1 by 0") +20 | +21 | with pytest.raises(socket.error): + | ^^^^^^^^^^^^ PT011 +22 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +22 | raise ValueError("Can't divide 1 by 0") +23 | +24 | with pytest.raises(PicklingError): + | ^^^^^^^^^^^^^ PT011 +25 | raise PicklingError("Can't pickle") + | + +PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +25 | raise PicklingError("Can't pickle") +26 | +27 | with pytest.raises(UnpicklingError): + | ^^^^^^^^^^^^^^^ PT011 +28 | raise UnpicklingError("Can't unpickle") + | + +PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +31 | def test_error_match_is_empty(): +32 | with pytest.raises(ValueError, match=None): + | ^^^^^^^^^^ PT011 +33 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +33 | raise ValueError("Can't divide 1 by 0") +34 | +35 | with pytest.raises(ValueError, match=""): + | ^^^^^^^^^^ PT011 +36 | raise ValueError("Can't divide 1 by 0") + | + +PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception + | +36 | raise ValueError("Can't divide 1 by 0") +37 | +38 | with pytest.raises(ValueError, match=f""): + | ^^^^^^^^^^ PT011 +39 | raise ValueError("Can't divide 1 by 0") + | + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap new file mode 100644 index 00000000000000..53d44920d6eb99 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/flake8_pytest_style/mod.rs +--- +PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +22 | raise ValueError("Can't divide 1 by 0") +23 | +24 | with pytest.raises(PicklingError): + | ^^^^^^^^^^^^^ PT011 +25 | raise PicklingError("Can't pickle") + | + +PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception + | +25 | raise PicklingError("Can't pickle") +26 | +27 | with pytest.raises(UnpicklingError): + | ^^^^^^^^^^^^^^^ PT011 +28 | raise UnpicklingError("Can't unpickle") + | + + diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap index a533ba0f815c33..9e4a8533c965d2 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_replace_broad_exceptions.snap @@ -1,12 +1,12 @@ --- source: crates/ruff/src/rules/flake8_pytest_style/mod.rs --- -PT011.py:12:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception +PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `match` parameter or use a more specific exception | -11 | def test_ok_different_error_from_config(): -12 | with pytest.raises(ZeroDivisionError): +12 | def test_ok_different_error_from_config(): +13 | with pytest.raises(ZeroDivisionError): | ^^^^^^^^^^^^^^^^^ PT011 -13 | raise ZeroDivisionError("Can't divide by 0") +14 | raise ZeroDivisionError("Can't divide by 0") | diff --git a/crates/ruff/src/settings/mod.rs b/crates/ruff/src/settings/mod.rs index ffae78aa08fe07..12bbd983347bcd 100644 --- a/crates/ruff/src/settings/mod.rs +++ b/crates/ruff/src/settings/mod.rs @@ -232,7 +232,8 @@ impl Settings { .unwrap_or_default(), flake8_pytest_style: config .flake8_pytest_style - .map(flake8_pytest_style::settings::Settings::from) + .map(flake8_pytest_style::settings::Settings::try_from) + .transpose()? .unwrap_or_default(), flake8_quotes: config .flake8_quotes From 2fbb09ba3723d975f7f0b0e11e6340915482195a Mon Sep 17 00:00:00 2001 From: harupy Date: Thu, 17 Aug 2023 08:42:47 +0900 Subject: [PATCH 2/4] Update schema --- ruff.schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruff.schema.json b/ruff.schema.json index 04ccd6b10fb990..552d8496907aaf 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -955,7 +955,7 @@ ] }, "raises-extend-require-match-for": { - "description": "List of additional exception names that require a match= parameter in a `pytest.raises()` call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.", + "description": "List of additional exception names that require a match= parameter in a `pytest.raises()` call. This extends the default list of exceptions that require a match= parameter. This option is useful if you want to extend the default list of exceptions that require a match= parameter without having to specify the entire list. Note that this option does not remove any exceptions from the default list.\n\nSupports glob patterns. For more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).", "type": [ "array", "null" @@ -965,7 +965,7 @@ } }, "raises-require-match-for": { - "description": "List of exception names that require a match= parameter in a `pytest.raises()` call.", + "description": "List of exception names that require a match= parameter in a `pytest.raises()` call.\n\nSupports glob patterns. For more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).", "type": [ "array", "null" From 0aafa7a04b00d8941fd63c219847d0a2bd129f7f Mon Sep 17 00:00:00 2001 From: harupy Date: Thu, 17 Aug 2023 09:01:57 +0900 Subject: [PATCH 3/4] rename --- crates/ruff/src/rules/flake8_pytest_style/mod.rs | 2 +- ...__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename crates/ruff/src/rules/flake8_pytest_style/snapshots/{ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap => ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap} (100%) diff --git a/crates/ruff/src/rules/flake8_pytest_style/mod.rs b/crates/ruff/src/rules/flake8_pytest_style/mod.rs index cf3da03273a461..fc73220c91d121 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/mod.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/mod.rs @@ -174,7 +174,7 @@ mod tests { raises_require_match_for: vec![IdentifierPattern::new("pickle.*").unwrap()], ..Settings::default() }, - "PT011_glob_submodule" + "PT011_glob_prefix" )] #[test_case( Rule::PytestRaisesWithMultipleStatements, diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap similarity index 100% rename from crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_submodule.snap rename to crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT011_glob_prefix.snap From 25a65f15ef97b5c2dce83a64b3ff8f8efd55bf6e Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 16 Aug 2023 22:05:21 -0400 Subject: [PATCH 4/4] Tweak allocation --- crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs index e3316f774fdc97..9510b294c7b147 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::format_call_path; @@ -231,6 +230,7 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .semantic() .resolve_call_path(exception) .and_then(|call_path| { + let call_path = format_call_path(&call_path); checker .settings .flake8_pytest_style @@ -242,10 +242,8 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) { .flake8_pytest_style .raises_extend_require_match_for, ) - .any(|pattern| { - pattern.matches(&call_path.iter().filter(|s| !s.is_empty()).join(".")) - }) - .then(|| format_call_path(&call_path)) + .any(|pattern| pattern.matches(&call_path)) + .then_some(call_path) }) { checker.diagnostics.push(Diagnostic::new(