diff --git a/superset/common/query_context_processor.py b/superset/common/query_context_processor.py index 9398caf47c..5a0468b671 100644 --- a/superset/common/query_context_processor.py +++ b/superset/common/query_context_processor.py @@ -19,13 +19,12 @@ from __future__ import annotations import copy import logging import re -from typing import Any, ClassVar, TYPE_CHECKING +from typing import Any, ClassVar, TYPE_CHECKING, TypedDict import numpy as np import pandas as pd from flask_babel import gettext as _ from pandas import DateOffset -from typing_extensions import TypedDict from superset import app from superset.common.chart_data import ChartDataResultFormat @@ -169,7 +168,7 @@ class QueryContextProcessor: cache.error_message = str(ex) cache.status = QueryStatus.FAILED - # the N-dimensional DataFrame has converteds into flat DataFrame + # the N-dimensional DataFrame has converted into flat DataFrame # by `flatten operator`, "comma" in the column is escaped by `escape_separator` # the result DataFrame columns should be unescaped label_map = { @@ -632,11 +631,6 @@ class QueryContextProcessor: return generate_cache_key(cache_dict, key_prefix) def get_annotation_data(self, query_obj: QueryObject) -> dict[str, Any]: - """ - :param query_context: - :param query_obj: - :return: - """ annotation_data: dict[str, Any] = self.get_native_annotation_data(query_obj) for annotation_layer in [ layer diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py index 2572f779d3..ebeea81ec6 100644 --- a/superset/db_engine_specs/base.py +++ b/superset/db_engine_specs/base.py @@ -23,7 +23,16 @@ import logging import re from datetime import datetime from re import Match, Pattern -from typing import Any, Callable, cast, ContextManager, NamedTuple, TYPE_CHECKING, Union +from typing import ( + Any, + Callable, + cast, + ContextManager, + NamedTuple, + TYPE_CHECKING, + TypedDict, + Union, +) import pandas as pd import sqlparse @@ -46,7 +55,6 @@ from sqlalchemy.sql import quoted_name, text from sqlalchemy.sql.expression import ColumnClause, Select, TextAsFrom, TextClause from sqlalchemy.types import TypeEngine from sqlparse.tokens import CTE -from typing_extensions import TypedDict from superset import security_manager, sql_parse from superset.constants import TimeGrain as TimeGrainConstants @@ -114,8 +122,8 @@ class TimestampExpression( ColumnClause ): # pylint: disable=abstract-method, too-many-ancestors def __init__(self, expr: str, col: ColumnClause, **kwargs: Any) -> None: - """Sqlalchemy class that can be can be used to render native column elements - respecting engine-specific quoting rules as part of a string-based expression. + """Sqlalchemy class that can be used to render native column elements respecting + engine-specific quoting rules as part of a string-based expression. :param expr: Sql expression with '{col}' denoting the locations where the col object will be rendered. @@ -331,7 +339,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods allows_alias_to_source_column = True # Whether ORDER BY clause must appear in SELECT - # if TRUE, then it doesn't have to. + # if True, then it doesn't have to. allows_hidden_orderby_agg = True # Whether ORDER BY clause can use sql calculated expression @@ -1000,7 +1008,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods to_sql_kwargs["name"] = table.table if table.schema: - # Only add schema when it is preset and non empty. + # Only add schema when it is preset and non-empty. to_sql_kwargs["schema"] = table.schema with cls.get_engine(database) as engine: @@ -1049,8 +1057,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods context = context or {} for regex, (message, error_type, extra) in cls.custom_errors.items(): - match = regex.search(raw_message) - if match: + if match := regex.search(raw_message): params = {**context, **match.groupdict()} extra["engine_name"] = cls.engine_name return [ @@ -1832,7 +1839,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods """ Construct an impersonation key, by default it's the given username. - :param user: logged in user + :param user: logged-in user :returns: username if given user is not null """ diff --git a/superset/db_engine_specs/bigquery.py b/superset/db_engine_specs/bigquery.py index 489ce396f6..f3b9c486e9 100644 --- a/superset/db_engine_specs/bigquery.py +++ b/superset/db_engine_specs/bigquery.py @@ -20,7 +20,7 @@ import re import urllib from datetime import datetime from re import Pattern -from typing import Any, Optional, TYPE_CHECKING +from typing import Any, Optional, TYPE_CHECKING, TypedDict import pandas as pd from apispec import APISpec @@ -33,7 +33,6 @@ from sqlalchemy import column, types from sqlalchemy.engine.base import Engine from sqlalchemy.engine.reflection import Inspector from sqlalchemy.sql import sqltypes -from typing_extensions import TypedDict from superset import sql_parse from superset.constants import PASSWORD_MASK, TimeGrain @@ -66,7 +65,6 @@ except ModuleNotFoundError: if TYPE_CHECKING: from superset.models.core import Database # pragma: no cover - CONNECTION_DATABASE_PERMISSIONS_REGEX = re.compile( "Access Denied: Project (?P.+?): User does not have " + "bigquery.jobs.create permission in project (?P.+?)" diff --git a/superset/db_engine_specs/databricks.py b/superset/db_engine_specs/databricks.py index d56f1e905f..1cbf4a238d 100644 --- a/superset/db_engine_specs/databricks.py +++ b/superset/db_engine_specs/databricks.py @@ -18,7 +18,7 @@ from __future__ import annotations import json from datetime import datetime -from typing import Any, TYPE_CHECKING +from typing import Any, TYPE_CHECKING, TypedDict from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin @@ -27,7 +27,6 @@ from marshmallow import fields, Schema from marshmallow.validate import Range from sqlalchemy.engine.reflection import Inspector from sqlalchemy.engine.url import URL -from typing_extensions import TypedDict from superset.constants import TimeGrain, USER_AGENT from superset.databases.utils import make_url_safe diff --git a/superset/db_engine_specs/gsheets.py b/superset/db_engine_specs/gsheets.py index 000a238cdb..b78a24ec12 100644 --- a/superset/db_engine_specs/gsheets.py +++ b/superset/db_engine_specs/gsheets.py @@ -22,7 +22,7 @@ import json import logging import re from re import Pattern -from typing import Any, TYPE_CHECKING +from typing import Any, TYPE_CHECKING, TypedDict import pandas as pd from apispec import APISpec @@ -34,7 +34,6 @@ from marshmallow.exceptions import ValidationError from requests import Session from sqlalchemy.engine import create_engine from sqlalchemy.engine.url import URL -from typing_extensions import TypedDict from superset import db, security_manager from superset.constants import PASSWORD_MASK diff --git a/superset/db_engine_specs/snowflake.py b/superset/db_engine_specs/snowflake.py index 879ec307c4..83d382cda1 100644 --- a/superset/db_engine_specs/snowflake.py +++ b/superset/db_engine_specs/snowflake.py @@ -19,7 +19,7 @@ import logging import re from datetime import datetime from re import Pattern -from typing import Any, Optional, TYPE_CHECKING +from typing import Any, Optional, TYPE_CHECKING, TypedDict from urllib import parse from apispec import APISpec @@ -32,7 +32,6 @@ from marshmallow import fields, Schema from sqlalchemy import types from sqlalchemy.engine.reflection import Inspector from sqlalchemy.engine.url import URL -from typing_extensions import TypedDict from superset.constants import TimeGrain, USER_AGENT from superset.databases.utils import make_url_safe diff --git a/superset/explore/form_data/commands/state.py b/superset/explore/form_data/commands/state.py index 35e3893478..806b4cde5a 100644 --- a/superset/explore/form_data/commands/state.py +++ b/superset/explore/form_data/commands/state.py @@ -14,9 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -from typing import Optional - -from typing_extensions import TypedDict +from typing import Optional, TypedDict from superset.utils.core import DatasourceType diff --git a/superset/jinja_context.py b/superset/jinja_context.py index 4bb0b91a4e..89f9c8ddcc 100644 --- a/superset/jinja_context.py +++ b/superset/jinja_context.py @@ -18,7 +18,7 @@ import json import re from functools import lru_cache, partial -from typing import Any, Callable, cast, Optional, TYPE_CHECKING, Union +from typing import Any, Callable, cast, Optional, TYPE_CHECKING, TypedDict, Union from flask import current_app, g, has_request_context, request from flask_babel import gettext as _ @@ -26,7 +26,6 @@ from jinja2 import DebugUndefined from jinja2.sandbox import SandboxedEnvironment from sqlalchemy.engine.interfaces import Dialect from sqlalchemy.types import String -from typing_extensions import TypedDict from superset.constants import LRU_CACHE_MAX_SIZE from superset.datasets.commands.exceptions import DatasetNotFoundError @@ -597,7 +596,7 @@ def get_template_processors() -> dict[str, Any]: processors = current_app.config.get("CUSTOM_TEMPLATE_PROCESSORS", {}) for engine, processor in DEFAULT_PROCESSORS.items(): # do not overwrite engine-specific CUSTOM_TEMPLATE_PROCESSORS - if not engine in processors: + if engine not in processors: processors[engine] = processor return processors diff --git a/superset/superset_typing.py b/superset/superset_typing.py index c58fa567ad..953683b5dc 100644 --- a/superset/superset_typing.py +++ b/superset/superset_typing.py @@ -16,9 +16,9 @@ # under the License. from collections.abc import Sequence from datetime import datetime -from typing import Any, Literal, Optional, TYPE_CHECKING, Union +from typing import Any, Literal, Optional, TYPE_CHECKING, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from werkzeug.wrappers import Response if TYPE_CHECKING: diff --git a/superset/temporary_cache/commands/entry.py b/superset/temporary_cache/commands/entry.py index 90aa8e1beb..22c7cd9670 100644 --- a/superset/temporary_cache/commands/entry.py +++ b/superset/temporary_cache/commands/entry.py @@ -14,9 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -from typing import Optional - -from typing_extensions import TypedDict +from typing import Optional, TypedDict class Entry(TypedDict): diff --git a/superset/utils/core.py b/superset/utils/core.py index 3e297b5c90..7cce8795ec 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -49,7 +49,7 @@ from enum import Enum, IntEnum from io import BytesIO from timeit import default_timer from types import TracebackType -from typing import Any, Callable, cast, NamedTuple, TYPE_CHECKING, TypeVar +from typing import Any, Callable, cast, NamedTuple, TYPE_CHECKING, TypedDict, TypeVar from urllib.parse import unquote_plus from zipfile import ZipFile @@ -73,7 +73,7 @@ from sqlalchemy.engine import Connection, Engine from sqlalchemy.engine.reflection import Inspector from sqlalchemy.sql.type_api import Variant from sqlalchemy.types import TEXT, TypeDecorator, TypeEngine -from typing_extensions import TypedDict, TypeGuard +from typing_extensions import TypeGuard from superset.constants import ( EXTRA_FORM_DATA_APPEND_KEYS, @@ -368,9 +368,9 @@ def flasher(msg: str, severity: str = "message") -> None: def parse_js_uri_path_item( item: str | None, unquote: bool = True, eval_undefined: bool = False ) -> str | None: - """Parse a uri path item made with js. + """Parse an uri path item made with js. - :param item: a uri path component + :param item: an uri path component :param unquote: Perform unquoting of string using urllib.parse.unquote_plus() :param eval_undefined: When set to True and item is either 'null' or 'undefined', assume item is undefined and return None. @@ -1162,16 +1162,14 @@ def merge_extra_filters(form_data: dict[str, Any]) -> None: filtr["isExtra"] = True # Pull out time filters/options and merge into form data filter_column = filtr["col"] - time_extra = date_options.get(filter_column) - if time_extra: + if time_extra := date_options.get(filter_column): time_extra_value = filtr.get("val") if time_extra_value and time_extra_value != NO_TIME_RANGE: form_data[time_extra] = time_extra_value form_data["applied_time_extras"][filter_column] = time_extra_value elif filtr["val"]: # Merge column filters - filter_key = get_filter_key(filtr) - if filter_key in existing_filters: + if (filter_key := get_filter_key(filtr)) in existing_filters: # Check if the filter already exists if isinstance(filtr["val"], list): if isinstance(existing_filters[filter_key], list): @@ -1268,11 +1266,9 @@ def get_column_name(column: Column, verbose_map: dict[str, Any] | None = None) - :raises ValueError: if metric object is invalid """ if isinstance(column, dict): - label = column.get("label") - if label: + if label := column.get("label"): return label - expr = column.get("sqlExpression") - if expr: + if expr := column.get("sqlExpression"): return expr if isinstance(column, str): @@ -1293,13 +1289,10 @@ def get_metric_name(metric: Metric, verbose_map: dict[str, Any] | None = None) - :raises ValueError: if metric object is invalid """ if is_adhoc_metric(metric): - label = metric.get("label") - if label: + if label := metric.get("label"): return label - expression_type = metric.get("expressionType") - if expression_type == "SQL": - sql_expression = metric.get("sqlExpression") - if sql_expression: + if (expression_type := metric.get("expressionType")) == "SQL": + if sql_expression := metric.get("sqlExpression"): return sql_expression if expression_type == "SIMPLE": column: AdhocMetricColumn = metric.get("column") or {} @@ -1753,9 +1746,8 @@ def get_time_filter_status( } ) - time_range = applied_time_extras.get(ExtraFiltersTimeColumnType.TIME_RANGE) - if time_range: - # are there any temporal columns to assign the time grain to? + if applied_time_extras.get(ExtraFiltersTimeColumnType.TIME_RANGE): + # are there any temporal columns to assign the time range to? if temporal_columns: applied.append({"column": ExtraFiltersTimeColumnType.TIME_RANGE}) else: diff --git a/superset/utils/mock_data.py b/superset/utils/mock_data.py index 7e215ed0be..fd49614215 100644 --- a/superset/utils/mock_data.py +++ b/superset/utils/mock_data.py @@ -23,7 +23,7 @@ import string import sys from collections.abc import Iterator from datetime import date, datetime, time, timedelta -from typing import Any, Callable, cast, Optional +from typing import Any, Callable, cast, Optional, TypedDict from uuid import uuid4 import sqlalchemy.sql.sqltypes @@ -34,7 +34,6 @@ from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Session from sqlalchemy.sql import func from sqlalchemy.sql.visitors import VisitableType -from typing_extensions import TypedDict from superset import db diff --git a/superset/views/datasource/schemas.py b/superset/views/datasource/schemas.py index daefb2a7ed..9c4b95b8da 100644 --- a/superset/views/datasource/schemas.py +++ b/superset/views/datasource/schemas.py @@ -14,10 +14,9 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -from typing import Any, Optional +from typing import Any, Optional, TypedDict from marshmallow import fields, post_load, pre_load, Schema, validate -from typing_extensions import TypedDict from superset import app from superset.charts.schemas import ChartDataExtrasSchema, ChartDataFilterSchema