You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2024/04/20 01:08:13 UTC

(superset) 02/02: test

This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin pushed a commit to branch ruff
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 82621e9b02c5cbc9cffacbe72ce9750b9706af05
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Fri Apr 19 17:39:33 2024 -0700

    test
---
 .pre-commit-config.yaml                          |  7 ---
 .pylintrc                                        |  4 +-
 pyproject.toml                                   | 78 ++++++++++++++++++++++++
 superset/cli/examples.py                         |  4 ++
 superset/commands/importers/v1/assets.py         |  1 -
 superset/common/query_object.py                  |  4 +-
 superset/models/core.py                          |  4 +-
 superset/models/helpers.py                       |  4 +-
 superset/sqllab/sqllab_execution_context.py      |  1 -
 superset/tags/models.py                          |  4 +-
 superset/tasks/celery_app.py                     |  3 -
 superset/utils/core.py                           |  4 +-
 superset/views/base_api.py                       |  3 +-
 tests/integration_tests/charts/data/api_tests.py |  5 +-
 tests/integration_tests/query_context_tests.py   | 23 +++++--
 tests/integration_tests/thumbnails_tests.py      | 76 +++++++++++++----------
 tests/unit_tests/thumbnails/test_digest.py       | 34 ++++++-----
 17 files changed, 184 insertions(+), 75 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ae96302d3f..1d3c64e10f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -19,13 +19,6 @@ repos:
     rev: v0.2.2
     hooks:
       - id: auto-walrus
-  - repo: https://github.com/asottile/pyupgrade
-    rev: v3.4.0
-    hooks:
-      - id: pyupgrade
-        exclude: scripts/change_detector.py
-        args:
-          - --py39-plus
   - repo: https://github.com/hadialqattan/pycln
     rev: v2.1.2
     hooks:
diff --git a/.pylintrc b/.pylintrc
index 1cab7a587a..bfbdbc0232 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -171,10 +171,10 @@ max-nested-blocks=5
 [FORMAT]
 
 # Maximum number of characters on a single line.
-max-line-length=90
+max-line-length=100
 
 # Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+ignore-long-lines=^\s*(# )?noqa.*$|^\s*(# )?<?https?://\S+>?$
 
 # Allow the body of an if to be on the same line as the test if there is no
 # else.
diff --git a/pyproject.toml b/pyproject.toml
index 858767e9eb..19d2319064 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -393,3 +393,81 @@ envlist =
     pylint
 skipsdist = true
 """
+[tool.ruff]
+# Exclude a variety of commonly ignored directories.
+exclude = [
+    ".bzr",
+    ".direnv",
+    ".eggs",
+    ".git",
+    ".git-rewrite",
+    ".hg",
+    ".ipynb_checkpoints",
+    ".mypy_cache",
+    ".nox",
+    ".pants.d",
+    ".pyenv",
+    ".pytest_cache",
+    ".pytype",
+    ".ruff_cache",
+    ".svn",
+    ".tox",
+    ".venv",
+    ".vscode",
+    "__pypackages__",
+    "_build",
+    "buck-out",
+    "build",
+    "dist",
+    "node_modules",
+    "site-packages",
+    "venv",
+]
+
+# Same as Black.
+line-length = 88
+indent-width = 4
+
+# Assume Python 3.8
+target-version = "py310"
+
+[tool.ruff.lint]
+# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by default.
+# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
+# McCabe complexity (`C901`) by default.
+select = ["E4", "E7", "E9", "F"]
+ignore = []
+
+# Allow fix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+[tool.ruff.format]
+# Like Black, use double quotes for strings.
+quote-style = "double"
+
+# Like Black, indent with spaces, rather than tabs.
+indent-style = "space"
+
+# Like Black, respect magic trailing commas.
+skip-magic-trailing-comma = false
+
+# Like Black, automatically detect the appropriate line ending.
+line-ending = "auto"
+
+# Enable auto-formatting of code examples in docstrings. Markdown,
+# reStructuredText code/literal blocks and doctests are all supported.
+#
+# This is currently disabled by default, but it is planned for this
+# to be opt-out in the future.
+docstring-code-format = false
+
+# Set the line length limit used when formatting code snippets in
+# docstrings.
+#
+# This only has an effect when the `docstring-code-format` setting is
+# enabled.
+docstring-code-line-length = "dynamic"
diff --git a/superset/cli/examples.py b/superset/cli/examples.py
index 3ce136ada7..60385f24e8 100755
--- a/superset/cli/examples.py
+++ b/superset/cli/examples.py
@@ -14,6 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+
+# pylint: disable=no-member
+# mypy: ignore-errors
+
 import logging
 
 import click
diff --git a/superset/commands/importers/v1/assets.py b/superset/commands/importers/v1/assets.py
index 876ce509ae..29a2dec179 100644
--- a/superset/commands/importers/v1/assets.py
+++ b/superset/commands/importers/v1/assets.py
@@ -112,7 +112,6 @@ class ImportAssetsCommand(BaseCommand):
             if file_name.startswith("charts/"):
                 dataset_dict = dataset_info[config["dataset_uuid"]]
                 config.update(dataset_dict)
-                # pylint: disable=line-too-long
                 dataset_uid = f"{dataset_dict['datasource_id']}__{dataset_dict['datasource_type']}"
                 config["params"].update({"datasource": dataset_uid})
                 if "query_context" in config:
diff --git a/superset/common/query_object.py b/superset/common/query_object.py
index 401eb251a6..b183532ebf 100644
--- a/superset/common/query_object.py
+++ b/superset/common/query_object.py
@@ -190,8 +190,8 @@ class QueryObject:  # pylint: disable=too-many-instance-attributes
             return isinstance(metric, str) or is_adhoc_metric(metric)
 
         self.metrics = metrics and [
-            x if is_str_or_adhoc(x) else x["label"]
-            for x in metrics  # type: ignore
+            x if is_str_or_adhoc(x) else x["label"]  # type: ignore
+            for x in metrics
         ]
 
     def _set_post_processing(
diff --git a/superset/models/core.py b/superset/models/core.py
index 53a3b1e1e4..d3509d0319 100755
--- a/superset/models/core.py
+++ b/superset/models/core.py
@@ -14,7 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-# pylint: disable=line-too-long,too-many-lines
+
+# pylint: disable=too-many-lines
+
 """A collection of ORM sqlalchemy models for Superset"""
 
 from __future__ import annotations
diff --git a/superset/models/helpers.py b/superset/models/helpers.py
index d0a814d113..32a9c5d65f 100644
--- a/superset/models/helpers.py
+++ b/superset/models/helpers.py
@@ -203,8 +203,8 @@ class ImportExportMixin:
         ]
         unique.extend(
             {c.name}
-            for c in cls.__table__.columns
-            if c.unique  # type: ignore
+            for c in cls.__table__.columns  # type: ignore
+            if c.unique
         )
         return unique
 
diff --git a/superset/sqllab/sqllab_execution_context.py b/superset/sqllab/sqllab_execution_context.py
index bcd0bcbf1d..7a732cf642 100644
--- a/superset/sqllab/sqllab_execution_context.py
+++ b/superset/sqllab/sqllab_execution_context.py
@@ -142,7 +142,6 @@ class SqlJsonExecutionContext:  # pylint: disable=too-many-instance-attributes
         self._sql_result = sql_result
 
     def create_query(self) -> Query:
-        # pylint: disable=line-too-long
         start_time = now_as_float()
         if self.select_as_cta:
             return Query(
diff --git a/superset/tags/models.py b/superset/tags/models.py
index e8610ddffc..ba859f519b 100644
--- a/superset/tags/models.py
+++ b/superset/tags/models.py
@@ -131,8 +131,8 @@ class TaggedObject(Model, AuditMixinNullable):
 
 def get_tag(
     name: str,
-    session: orm.Session,
-    type_: TagType,  # pylint: disable=disallowed-name
+    session: orm.Session,  # pylint: disable=disallowed-name
+    type_: TagType,
 ) -> Tag:
     tag_name = name.strip()
     tag = session.query(Tag).filter_by(name=tag_name, type=type_).one_or_none()
diff --git a/superset/tasks/celery_app.py b/superset/tasks/celery_app.py
index 892aa01221..32f8fbbe79 100644
--- a/superset/tasks/celery_app.py
+++ b/superset/tasks/celery_app.py
@@ -31,9 +31,6 @@ from superset.extensions import celery_app, db
 # Init the Flask app / configure everything
 flask_app = create_app()
 
-# Need to import late, as the celery_app will have been setup by "create_app()"
-# pylint: disable=wrong-import-position, unused-import
-
 # Export the celery app globally for Celery (as run on the cmd line) to find
 app = celery_app
 
diff --git a/superset/utils/core.py b/superset/utils/core.py
index 81b437054a..2ff4ec0937 100644
--- a/superset/utils/core.py
+++ b/superset/utils/core.py
@@ -1051,8 +1051,8 @@ def merge_extra_form_data(form_data: dict[str, Any]) -> None:
         "adhoc_filters", []
     )
     adhoc_filters.extend(
-        {"isExtra": True, **fltr}
-        for fltr in append_adhoc_filters  # type: ignore
+        {"isExtra": True, **fltr}  # type: ignore
+        for fltr in append_adhoc_filters
     )
     if append_filters:
         for key, value in form_data.items():
diff --git a/superset/views/base_api.py b/superset/views/base_api.py
index 0f67b780eb..a62e963149 100644
--- a/superset/views/base_api.py
+++ b/superset/views/base_api.py
@@ -247,7 +247,8 @@ class BaseSupersetApiMixin:
             self.timing_stats("time", key, time_delta)
 
 
-class BaseSupersetApi(BaseSupersetApiMixin, BaseApi): ...
+class BaseSupersetApi(BaseSupersetApiMixin, BaseApi):
+    pass
 
 
 class BaseSupersetModelRestApi(BaseSupersetApiMixin, ModelRestApi):
diff --git a/tests/integration_tests/charts/data/api_tests.py b/tests/integration_tests/charts/data/api_tests.py
index 3ae848172b..06dfbf8f36 100644
--- a/tests/integration_tests/charts/data/api_tests.py
+++ b/tests/integration_tests/charts/data/api_tests.py
@@ -121,7 +121,9 @@ class BaseTestChartDataApi(SupersetTestCase):
 
     def quote_name(self, name: str):
         if get_main_database().backend in {"presto", "hive"}:
-            with get_example_database().get_inspector_with_context() as inspector:  # E: Ne
+            with (
+                get_example_database().get_inspector_with_context() as inspector
+            ):  # E: Ne
                 return inspector.engine.dialect.identifier_preparer.quote_identifier(
                     name
                 )
@@ -1315,6 +1317,7 @@ def test_cache_default_timeout(test_client, login_as_admin, physical_query_conte
 def test_custom_cache_timeout(test_client, login_as_admin, physical_query_context):
     physical_query_context["custom_cache_timeout"] = 5678
     rv = test_client.post(CHART_DATA_URI, json=physical_query_context)
+
     assert rv.json["result"][0]["cache_timeout"] == 5678
 
 
diff --git a/tests/integration_tests/query_context_tests.py b/tests/integration_tests/query_context_tests.py
index 3a14c37a43..98b3f2ef95 100644
--- a/tests/integration_tests/query_context_tests.py
+++ b/tests/integration_tests/query_context_tests.py
@@ -16,7 +16,7 @@
 # under the License.
 import re
 import time
-from typing import Any
+from typing import Any, Optional
 from unittest.mock import Mock, patch
 
 import numpy as np
@@ -200,14 +200,29 @@ class TestQueryContext(SupersetTestCase):
         # the new cache_key should be different due to updated datasource
         self.assertNotEqual(cache_key_original, cache_key_new)
 
-    def test_query_cache_key_does_not_change_for_non_existent_or_null(self):
-        payload = get_query_context("birth_names", add_postprocessing_operations=True)
+    def test_query_cache_key_does_not_change_for_non_existent_or_null(
+        self,
+        # pylint: disable=unused-argument
+        payload: dict[str, Any] = get_query_context(
+            "birth_names", add_postprocessing_operations=True
+        ),
+    ) -> None:
+        """
+        Ensure query_cache_key does not change when granularity is missing or None
+
+        Args:
+            payload (dict): query context payload
+
+        Returns:
+            None
+
+        """
         del payload["queries"][0]["granularity"]
 
         # construct baseline query_cache_key from query_context with post processing operation
         query_context: QueryContext = ChartDataQueryContextSchema().load(payload)
         query_object: QueryObject = query_context.queries[0]
-        cache_key_original = query_context.query_cache_key(query_object)
+        cache_key_original: Optional[str] = query_context.query_cache_key(query_object)
 
         payload["queries"][0]["granularity"] = None
         query_context = ChartDataQueryContextSchema().load(payload)
diff --git a/tests/integration_tests/thumbnails_tests.py b/tests/integration_tests/thumbnails_tests.py
index cadabfe47d..4f2946cc94 100644
--- a/tests/integration_tests/thumbnails_tests.py
+++ b/tests/integration_tests/thumbnails_tests.py
@@ -233,14 +233,17 @@ class TestThumbnails(SupersetTestCase):
         Thumbnails: Simple get async dashboard screenshot as selenium user
         """
         self.login(ALPHA_USERNAME)
-        with patch.dict(
-            "superset.thumbnails.digest.current_app.config",
-            {
-                "THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
-            },
-        ), patch(
-            "superset.thumbnails.digest._adjust_string_for_executor"
-        ) as mock_adjust_string:
+        with (
+            patch.dict(
+                "superset.thumbnails.digest.current_app.config",
+                {
+                    "THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
+                },
+            ),
+            patch(
+                "superset.thumbnails.digest._adjust_string_for_executor"
+            ) as mock_adjust_string,
+        ):
             mock_adjust_string.return_value = self.digest_return_value
             _, thumbnail_url = self._get_id_and_thumbnail_url(DASHBOARD_URL)
             assert self.digest_hash in thumbnail_url
@@ -258,14 +261,17 @@ class TestThumbnails(SupersetTestCase):
         """
         username = "alpha"
         self.login(username)
-        with patch.dict(
-            "superset.thumbnails.digest.current_app.config",
-            {
-                "THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
-            },
-        ), patch(
-            "superset.thumbnails.digest._adjust_string_for_executor"
-        ) as mock_adjust_string:
+        with (
+            patch.dict(
+                "superset.thumbnails.digest.current_app.config",
+                {
+                    "THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
+                },
+            ),
+            patch(
+                "superset.thumbnails.digest._adjust_string_for_executor"
+            ) as mock_adjust_string,
+        ):
             mock_adjust_string.return_value = self.digest_return_value
             _, thumbnail_url = self._get_id_and_thumbnail_url(DASHBOARD_URL)
             assert self.digest_hash in thumbnail_url
@@ -305,14 +311,17 @@ class TestThumbnails(SupersetTestCase):
         Thumbnails: Simple get async chart screenshot as selenium user
         """
         self.login(ADMIN_USERNAME)
-        with patch.dict(
-            "superset.thumbnails.digest.current_app.config",
-            {
-                "THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
-            },
-        ), patch(
-            "superset.thumbnails.digest._adjust_string_for_executor"
-        ) as mock_adjust_string:
+        with (
+            patch.dict(
+                "superset.thumbnails.digest.current_app.config",
+                {
+                    "THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
+                },
+            ),
+            patch(
+                "superset.thumbnails.digest._adjust_string_for_executor"
+            ) as mock_adjust_string,
+        ):
             mock_adjust_string.return_value = self.digest_return_value
             _, thumbnail_url = self._get_id_and_thumbnail_url(CHART_URL)
             assert self.digest_hash in thumbnail_url
@@ -330,14 +339,17 @@ class TestThumbnails(SupersetTestCase):
         """
         username = "alpha"
         self.login(username)
-        with patch.dict(
-            "superset.thumbnails.digest.current_app.config",
-            {
-                "THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
-            },
-        ), patch(
-            "superset.thumbnails.digest._adjust_string_for_executor"
-        ) as mock_adjust_string:
+        with (
+            patch.dict(
+                "superset.thumbnails.digest.current_app.config",
+                {
+                    "THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
+                },
+            ),
+            patch(
+                "superset.thumbnails.digest._adjust_string_for_executor"
+            ) as mock_adjust_string,
+        ):
             mock_adjust_string.return_value = self.digest_return_value
             _, thumbnail_url = self._get_id_and_thumbnail_url(CHART_URL)
             assert self.digest_hash in thumbnail_url
diff --git a/tests/unit_tests/thumbnails/test_digest.py b/tests/unit_tests/thumbnails/test_digest.py
index 68bd7a58f7..987488ffe7 100644
--- a/tests/unit_tests/thumbnails/test_digest.py
+++ b/tests/unit_tests/thumbnails/test_digest.py
@@ -172,13 +172,16 @@ def test_dashboard_digest(
         user = User(id=1, username="1")
     func = CUSTOM_DASHBOARD_FUNC if use_custom_digest else None
 
-    with patch.dict(
-        app.config,
-        {
-            "THUMBNAIL_EXECUTE_AS": execute_as,
-            "THUMBNAIL_DASHBOARD_DIGEST_FUNC": func,
-        },
-    ), override_user(user):
+    with (
+        patch.dict(
+            app.config,
+            {
+                "THUMBNAIL_EXECUTE_AS": execute_as,
+                "THUMBNAIL_DASHBOARD_DIGEST_FUNC": func,
+            },
+        ),
+        override_user(user),
+    ):
         cm = (
             pytest.raises(type(expected_result))
             if isinstance(expected_result, Exception)
@@ -242,13 +245,16 @@ def test_chart_digest(
         user = User(id=1, username="1")
     func = CUSTOM_CHART_FUNC if use_custom_digest else None
 
-    with patch.dict(
-        app.config,
-        {
-            "THUMBNAIL_EXECUTE_AS": execute_as,
-            "THUMBNAIL_CHART_DIGEST_FUNC": func,
-        },
-    ), override_user(user):
+    with (
+        patch.dict(
+            app.config,
+            {
+                "THUMBNAIL_EXECUTE_AS": execute_as,
+                "THUMBNAIL_CHART_DIGEST_FUNC": func,
+            },
+        ),
+        override_user(user),
+    ):
         cm = (
             pytest.raises(type(expected_result))
             if isinstance(expected_result, Exception)