Repository: mlflow/mlflow

Issue:
Enable `PT011`
### Summary

Enable https://beta.ruff.rs/docs/rules/pytest-raises-too-broad.

```diff
diff --git a/pyproject.toml b/pyproject.toml
index c373b48ca..8b7810c04 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,6 +25,7 @@ select = [
   "PT009",
   "PT010",
   "PT012",
+  "PT011",
   "PT013",
   "PT018",
   "PT022",
@@ -72,6 +73,7 @@ extend-exclude = [
 [tool.ruff.flake8-pytest-style]
 mark-parentheses = false
 fixture-parentheses = false
+raises-require-match-for = ["*"]
 
 [tool.ruff.flake8-tidy-imports]
 ban-relative-imports = "all"
```

- `raises-require-match-for = ["*"]` means all errors require `match`.

### Notes

- Make sure to open a PR from a **non-master** branch.
- Sign off the commit using the `-s` flag when making a commit:

  ```sh
  git commit -s -m "..."
           # ^^ make sure to use this
  ```

- Include `#{issue_number}` (e.g. `#123`) in the PR description when opening a PR.



Discussion:
cc @Increshi
@Increshi Can you post a comment so that I can assign this issue to you?

Resolving patch:
diff --git a/pylint_plugins/__init__.py b/pylint_plugins/__init__.py
--- a/pylint_plugins/__init__.py
+++ b/pylint_plugins/__init__.py
@@ -1,11 +1,9 @@
-from pylint_plugins.pytest_raises_checker import PytestRaisesChecker
 from pylint_plugins.unittest_assert_raises import UnittestAssertRaises
 from pylint_plugins.import_checker import ImportChecker
 from pylint_plugins.assign_checker import AssignChecker
 
 
 def register(linter):
-    linter.register_checker(PytestRaisesChecker(linter))
     linter.register_checker(UnittestAssertRaises(linter))
     linter.register_checker(ImportChecker(linter))
     linter.register_checker(AssignChecker(linter))
diff --git a/pylint_plugins/errors.py b/pylint_plugins/errors.py
--- a/pylint_plugins/errors.py
+++ b/pylint_plugins/errors.py
@@ -16,14 +16,6 @@ def to_msgs(*messages: Message) -> Dict[str, Tuple[str, str, str]]:
     return reduce(lambda x, y: {**x, **y.to_dict()}, messages, {})
 
 
-PYTEST_RAISES_WITHOUT_MATCH = Message(
-    id="W0001",
-    name="pytest-raises-without-match",
-    message="`pytest.raises` must be called with `match` argument`.",
-    reason="`pytest.raises` without `match` argument can lead to false positives.",
-)
-
-
 UNITTEST_PYTEST_RAISES = Message(
     id="W0003",
     name="unittest-assert-raises",
diff --git a/pylint_plugins/pytest_raises_checker/__init__.py b/pylint_plugins/pytest_raises_checker/__init__.py
deleted file mode 100644
--- a/pylint_plugins/pytest_raises_checker/__init__.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import astroid
-from pylint.interfaces import IAstroidChecker
-from pylint.checkers import BaseChecker
-
-from pylint_plugins.errors import PYTEST_RAISES_WITHOUT_MATCH, to_msgs
-
-
-def _is_pytest_raises_call(node: astroid.NodeNG):
-    if not isinstance(node, astroid.Call):
-        return False
-    if not isinstance(node.func, astroid.Attribute) or not isinstance(node.func.expr, astroid.Name):
-        return False
-    return node.func.expr.name == "pytest" and node.func.attrname == "raises"
-
-
-def _called_with_match(node: astroid.Call):
-    # Note `match` is a keyword-only argument:
-    # https://docs.pytest.org/en/latest/reference/reference.html#pytest.raises
-    return any(k.arg == "match" for k in node.keywords)
-
-
-def _contains_multiple_statements(raises_with: astroid.With):
-    return len(raises_with.body) > 1
-
-
-class PytestRaisesChecker(BaseChecker):
-    __implements__ = IAstroidChecker
-
-    name = "pytest-raises-checker"
-    msgs = to_msgs(PYTEST_RAISES_WITHOUT_MATCH)
-    priority = -1
-
-    def visit_call(self, node: astroid.Call):
-        if not _is_pytest_raises_call(node):
-            return
-
-        if not _called_with_match(node):
-            self.add_message(PYTEST_RAISES_WITHOUT_MATCH.name, node=node)


Test patch:
diff --git a/pylint_plugins/tests/test_pytest_raises_checker.py b/pylint_plugins/tests/test_pytest_raises_checker.py
deleted file mode 100644
--- a/pylint_plugins/tests/test_pytest_raises_checker.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import pytest
-import astroid
-from pylint.testutils import MessageTest
-from pylint.testutils import CheckerTestCase
-
-from pylint_plugins import PytestRaisesChecker
-
-
-@pytest.fixture(scope="module")
-def test_case():
-    class TestPytestRaisesWithoutMatch(CheckerTestCase):
-        CHECKER_CLASS = PytestRaisesChecker
-
-    test_case = TestPytestRaisesWithoutMatch()
-    test_case.setup_method()
-    return test_case
-
-
-def without_raises_bad_cases():
-    # Single context manager
-    root_node = astroid.extract_node(
-        """
-with pytest.raises(Exception):
-    raise Exception("failed")
-"""
-    )
-    yield root_node, root_node.items[0][0], (2, 5)
-
-    # Multiple context managers
-    root_node = astroid.extract_node(
-        """
-with context_manager, pytest.raises(Exception):
-    raise Exception("failed")
-"""
-    )
-    yield root_node, root_node.items[1][0], (2, 22)
-
-    # Without `with`
-    root_node = astroid.extract_node(
-        """
-pytest.raises(Exception)
-"""
-    )
-    yield root_node, root_node, (2, 0)
-
-
-def without_raises_iter_good_cases():
-    # Single context manager
-    yield astroid.extract_node(
-        """
-with pytest.raises(Exception, match="failed"):
-    raise Exception("failed")
-"""
-    )
-
-    # Multiple context managers
-    yield astroid.extract_node(
-        """
-with context_manager, pytest.raises(Exception, match="failed"):
-    raise Exception("failed")
-"""
-    )
-
-    # Without `with`
-    yield astroid.extract_node(
-        """
-pytest.raises(Exception, match="failed")
-"""
-    )
-
-
-def test_without_raises(test_case):
-    for root_node, error_node, (line, col_offset) in without_raises_bad_cases():
-        with test_case.assertAddsMessages(
-            MessageTest(
-                "pytest-raises-without-match",
-                node=error_node,
-                line=line,
-                col_offset=col_offset,
-            )
-        ):
-            test_case.walk(root_node)
-
-    for root_node in without_raises_iter_good_cases():
-        with test_case.assertNoMessages():
-            test_case.walk(root_node)
diff --git a/tests/autologging/test_autologging_safety_unit.py b/tests/autologging/test_autologging_safety_unit.py
--- a/tests/autologging/test_autologging_safety_unit.py
+++ b/tests/autologging/test_autologging_safety_unit.py
@@ -1096,7 +1096,7 @@ def original():
         "test_integration", lambda original, *args, **kwargs: original(*args, **kwargs)
     )
 
-    with pytest.raises(KeyboardInterrupt, match=""):
+    with pytest.raises(KeyboardInterrupt, match=r".*"):
         patch_function_1(original)
 
     assert not mlflow.active_run()
@@ -1112,7 +1112,7 @@ def _on_exception(self, exception):
 
     patch_function_2 = with_managed_run("test_integration", PatchFunction2)
 
-    with pytest.raises(KeyboardInterrupt, match=""):
+    with pytest.raises(KeyboardInterrupt, match=r".*"):
         patch_function_2.call(original)
 
     assert not mlflow.active_run()
diff --git a/tests/autologging/test_autologging_utils.py b/tests/autologging/test_autologging_utils.py
--- a/tests/autologging/test_autologging_utils.py
+++ b/tests/autologging/test_autologging_utils.py
@@ -913,9 +913,9 @@ def f4(self, *args, **kwargs):
     assert get_instance_method_first_arg_value(Test.f1, [3], {"cd2": 4}) == 3
     assert get_instance_method_first_arg_value(Test.f1, [], {"ab1": 3, "cd2": 4}) == 3
     assert get_instance_method_first_arg_value(Test.f2, [3, 4], {}) == 3
-    with pytest.raises(AssertionError, match=""):
+    with pytest.raises(AssertionError, match=r".*"):
         get_instance_method_first_arg_value(Test.f3, [], {"ab1": 3, "cd2": 4})
-    with pytest.raises(AssertionError, match=""):
+    with pytest.raises(AssertionError, match=r".*"):
         get_instance_method_first_arg_value(Test.f4, [], {"ab1": 3, "cd2": 4})
 
 
diff --git a/tests/pyfunc/test_spark.py b/tests/pyfunc/test_spark.py
--- a/tests/pyfunc/test_spark.py
+++ b/tests/pyfunc/test_spark.py
@@ -845,7 +845,7 @@ def run_job():
     time.sleep(10)  # waiting server to exit and release the port.
 
     # assert ping failed, i.e. the server process is killed successfully.
-    with pytest.raises(Exception):  # pylint: disable=pytest-raises-without-match
+    with pytest.raises(Exception, match=r".*"):
         client.ping()
 
 
diff --git a/tests/types/test_schema.py b/tests/types/test_schema.py
--- a/tests/types/test_schema.py
+++ b/tests/types/test_schema.py
@@ -936,7 +936,7 @@ def test_infer_param_schema():
         "d": [[1, 2], [3, 4]],
         "e": {"a": 1, "b": 2},
     }
-    with pytest.raises(MlflowException) as e:  # pylint: disable=pytest-raises-without-match
+    with pytest.raises(MlflowException, match=r".*") as e:
         _infer_param_schema(test_parameters)
     assert e.match(r"Failed to infer schema for parameters: ")
     assert e.match(