Repository: mlflow/mlflow

Issue:
Upgrade `pylint` to  `2.14.4`
We currently use pylint 2.11.1. This is a bit old so we should upgrade it to the latest version (2.14.4):

https://github.com/mlflow/mlflow/blob/d40780be361f4bd2741c2e8fcbd428c1d693edcf/requirements/lint-requirements.txt#L1

- https://pypi.org/project/pylint/2.11.1/
- https://pypi.org/project/pylint/2.14.4/


Discussion:
Note pylint 2.14.4 might detect lint errors that 2.11.1 doesn't.
Is this being worked on? If not I would like to make this tiny change as a first issue.
@KarthikKothareddy No, I just assigned myself as a reviewer. Looking forward to your PR :)
Thank you let me make that change and submit a PR :) 

Resolving patch:
diff --git a/mlflow/utils/autologging_utils/logging_and_warnings.py b/mlflow/utils/autologging_utils/logging_and_warnings.py
--- a/mlflow/utils/autologging_utils/logging_and_warnings.py
+++ b/mlflow/utils/autologging_utils/logging_and_warnings.py
@@ -62,7 +62,7 @@ def _patched_showwarning(self, message, category, filename, lineno, *args, **kwa
             is_mlflow_warning and self._mlflow_warnings_rerouted_to_event_logs
         ):
             _logger.warning(
-                "MLflow autologging encountered a warning:" ' "%s:%d: %s: %s"',
+                'MLflow autologging encountered a warning: "%s:%d: %s: %s"',
                 filename,
                 lineno,
                 category.__name__,


Test patch:
diff --git a/tests/autologging/fixtures.py b/tests/autologging/fixtures.py
--- a/tests/autologging/fixtures.py
+++ b/tests/autologging/fixtures.py
@@ -37,8 +37,8 @@ def throw_error_fn(self, error_to_raise):
 
 @pytest.fixture
 def test_mode_off():
+    prev_env_var_value = os.environ.pop(_AUTOLOGGING_TEST_MODE_ENV_VAR, None)
     try:
-        prev_env_var_value = os.environ.pop(_AUTOLOGGING_TEST_MODE_ENV_VAR, None)
         os.environ[_AUTOLOGGING_TEST_MODE_ENV_VAR] = "false"
         assert not is_testing()
         yield
@@ -50,8 +50,8 @@ def test_mode_off():
 
 
 def enable_test_mode():
+    prev_env_var_value = os.environ.pop(_AUTOLOGGING_TEST_MODE_ENV_VAR, None)
     try:
-        prev_env_var_value = os.environ.pop(_AUTOLOGGING_TEST_MODE_ENV_VAR, None)
         os.environ[_AUTOLOGGING_TEST_MODE_ENV_VAR] = "true"
         assert is_testing()
         yield
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
@@ -146,8 +146,8 @@ def log_original_function_error(
 
 @pytest.fixture
 def mock_event_logger():
+    prev_logger = AutologgingEventLogger.get_logger()
     try:
-        prev_logger = AutologgingEventLogger.get_logger()
         logger = MockEventLogger()
         AutologgingEventLogger.set_logger(logger)
         yield logger
@@ -156,8 +156,8 @@ def mock_event_logger():
 
 
 def test_is_testing_respects_environment_variable():
+    prev_env_var_value = os.environ.pop("MLFLOW_AUTOLOGGING_TESTING", None)
     try:
-        prev_env_var_value = os.environ.pop("MLFLOW_AUTOLOGGING_TESTING", None)
         assert not is_testing()
 
         os.environ["MLFLOW_AUTOLOGGING_TESTING"] = "false"
diff --git a/tests/pylint_plugins/test_print_function.py b/tests/pylint_plugins/test_print_function.py
--- a/tests/pylint_plugins/test_print_function.py
+++ b/tests/pylint_plugins/test_print_function.py
@@ -20,7 +20,9 @@ class TestPrintFunction(pylint.testutils.CheckerTestCase):
 
 def test_print_function(test_case):
     node = extract_node("print('hello')")
-    with test_case.assertAddsMessages(create_message(test_case.CHECKER_CLASS.name, node)):
+    with test_case.assertAddsMessages(
+        create_message(test_case.CHECKER_CLASS.name, node, line=1, col_offset=0)
+    ):
         test_case.walk(node)
 
     node = extract_node("module.print('hello')")
diff --git a/tests/pylint_plugins/test_pytest_raises_without_match.py b/tests/pylint_plugins/test_pytest_raises_without_match.py
--- a/tests/pylint_plugins/test_pytest_raises_without_match.py
+++ b/tests/pylint_plugins/test_pytest_raises_without_match.py
@@ -27,7 +27,7 @@ def iter_bad_cases():
     raise Exception("failed")
 """
     )
-    yield root_node, root_node.items[0][0]
+    yield root_node, root_node.items[0][0], (2, 5)
 
     # Multiple context managers
     root_node = extract_node(
@@ -36,7 +36,7 @@ def iter_bad_cases():
     raise Exception("failed")
 """
     )
-    yield root_node, root_node.items[1][0]
+    yield root_node, root_node.items[1][0], (2, 22)
 
     # Without `with`
     root_node = extract_node(
@@ -44,12 +44,14 @@ def iter_bad_cases():
 pytest.raises(Exception)
 """
     )
-    yield root_node, root_node
+    yield root_node, root_node, (2, 0)
 
 
 def test_bad_cases(test_case):
-    for root_node, error_node in iter_bad_cases():
-        with test_case.assertAddsMessages(create_message(test_case.CHECKER_CLASS.name, error_node)):
+    for root_node, error_node, (line, col_offset) in iter_bad_cases():
+        with test_case.assertAddsMessages(
+            create_message(test_case.CHECKER_CLASS.name, error_node, line, col_offset)
+        ):
             test_case.walk(root_node)
 
 
diff --git a/tests/pylint_plugins/test_unittest_assert_raises.py b/tests/pylint_plugins/test_unittest_assert_raises.py
--- a/tests/pylint_plugins/test_unittest_assert_raises.py
+++ b/tests/pylint_plugins/test_unittest_assert_raises.py
@@ -20,7 +20,9 @@ class TestUnittestAssertRaises(pylint.testutils.CheckerTestCase):
 
 def test_unittest_assert_raises(test_case):
     node = extract_node("self.assertRaises(Exception)")
-    with test_case.assertAddsMessages(create_message(test_case.CHECKER_CLASS.name, node)):
+    with test_case.assertAddsMessages(
+        create_message(test_case.CHECKER_CLASS.name, node, line=1, col_offset=0)
+    ):
         test_case.walk(node)
 
     node = extract_node("self.assertRaisesRegex(Exception, 'error message')")
diff --git a/tests/pylint_plugins/utils.py b/tests/pylint_plugins/utils.py
--- a/tests/pylint_plugins/utils.py
+++ b/tests/pylint_plugins/utils.py
@@ -20,10 +20,10 @@ def get_pylint_msg_ids():
     return set(re.findall(rf"\(([{letters}][0-9]{{4}})\)", stdout))
 
 
-def create_message(msg_id, node):
+def create_message(msg_id, node, line=None, col_offset=None):
     import pylint.testutils
 
-    return pylint.testutils.Message(msg_id=msg_id, node=node)
+    return pylint.testutils.MessageTest(msg_id=msg_id, node=node, line=line, col_offset=col_offset)
 
 
 def extract_node(code):
diff --git a/tests/shap/test_shap.py b/tests/shap/test_shap.py
--- a/tests/shap/test_shap.py
+++ b/tests/shap/test_shap.py
@@ -174,11 +174,8 @@ def test_log_explanation_without_active_run(regressor):
     model = regressor.model
     X = regressor.X.values
 
-    try:
+    with mlflow.start_run() as run:
         explanation_uri = mlflow.shap.log_explanation(model.predict, X)
-    finally:
-        run = mlflow.active_run()
-        mlflow.end_run()
 
         # Assert no figure is open
         assert len(plt.get_fignums()) == 0
diff --git a/tests/store/tracking/test_sqlalchemy_store.py b/tests/store/tracking/test_sqlalchemy_store.py
--- a/tests/store/tracking/test_sqlalchemy_store.py
+++ b/tests/store/tracking/test_sqlalchemy_store.py
@@ -2225,7 +2225,7 @@ def test_search_runs_correctly_filters_large_data(self):
 
         run_results = self.store.search_runs(
             [experiment_id],
-            "metrics.mkey_0 < 26 and metrics.mkey_0 > 5 " "and tags.tkey_0 = 'tval_0' ",
+            "metrics.mkey_0 < 26 and metrics.mkey_0 > 5 and tags.tkey_0 = 'tval_0' ",
             ViewType.ALL,
             max_results=10,
         )
diff --git a/tests/tracking/fluent/test_fluent.py b/tests/tracking/fluent/test_fluent.py
--- a/tests/tracking/fluent/test_fluent.py
+++ b/tests/tracking/fluent/test_fluent.py
@@ -342,8 +342,8 @@ def test_list_experiments(view_type, tmpdir):
         ]
         session.add_all(experiments)
 
+    url, process = _init_server(sqlite_uri, root_artifact_uri=tmpdir.strpath)
     try:
-        url, process = _init_server(sqlite_uri, root_artifact_uri=tmpdir.strpath)
         mlflow.set_tracking_uri(url)
         # `max_results` is unspecified
         assert len(mlflow.list_experiments(view_type)) == num_experiments