diff --git a/.pylintrc b/.pylintrc index e921ee5ac80bf..96329041731ec 100644 --- a/.pylintrc +++ b/.pylintrc @@ -84,7 +84,6 @@ confidence= disable= missing-docstring, too-many-lines, - raise-missing-from, duplicate-code, [REPORTS] diff --git a/superset/annotation_layers/annotations/commands/bulk_delete.py b/superset/annotation_layers/annotations/commands/bulk_delete.py index 9d9df6fab85fe..6a164c877da8b 100644 --- a/superset/annotation_layers/annotations/commands/bulk_delete.py +++ b/superset/annotation_layers/annotations/commands/bulk_delete.py @@ -44,7 +44,7 @@ def run(self) -> None: return None except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise AnnotationBulkDeleteFailedError() + raise AnnotationBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists diff --git a/superset/annotation_layers/annotations/commands/create.py b/superset/annotation_layers/annotations/commands/create.py index 398e1b4c54421..cbcb09a4c5ce9 100644 --- a/superset/annotation_layers/annotations/commands/create.py +++ b/superset/annotation_layers/annotations/commands/create.py @@ -48,7 +48,7 @@ def run(self) -> Model: annotation = AnnotationDAO.create(self._properties) except DAOCreateFailedError as ex: logger.exception(ex.exception) - raise AnnotationCreateFailedError() + raise AnnotationCreateFailedError() from ex return annotation def validate(self) -> None: diff --git a/superset/annotation_layers/annotations/commands/delete.py b/superset/annotation_layers/annotations/commands/delete.py index bd5c998a594e9..3d874818dc6cb 100644 --- a/superset/annotation_layers/annotations/commands/delete.py +++ b/superset/annotation_layers/annotations/commands/delete.py @@ -44,7 +44,7 @@ def run(self) -> Model: annotation = AnnotationDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise AnnotationDeleteFailedError() + raise AnnotationDeleteFailedError() from ex return annotation def validate(self) -> None: diff --git a/superset/annotation_layers/annotations/commands/update.py b/superset/annotation_layers/annotations/commands/update.py index 1942bffa7f712..eb544344f1eaa 100644 --- a/superset/annotation_layers/annotations/commands/update.py +++ b/superset/annotation_layers/annotations/commands/update.py @@ -52,7 +52,7 @@ def run(self) -> Model: annotation = AnnotationDAO.update(self._model, self._properties) except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise AnnotationUpdateFailedError() + raise AnnotationUpdateFailedError() from ex return annotation def validate(self) -> None: diff --git a/superset/annotation_layers/annotations/dao.py b/superset/annotation_layers/annotations/dao.py index 50e4bcb29aee1..3b6e5e72e7099 100644 --- a/superset/annotation_layers/annotations/dao.py +++ b/superset/annotation_layers/annotations/dao.py @@ -39,10 +39,10 @@ def bulk_delete(models: Optional[List[Annotation]], commit: bool = True) -> None ) if commit: db.session.commit() - except SQLAlchemyError: + except SQLAlchemyError as ex: if commit: db.session.rollback() - raise DAODeleteFailedError() + raise DAODeleteFailedError() from ex @staticmethod def validate_update_uniqueness( diff --git a/superset/annotation_layers/annotations/schemas.py b/superset/annotation_layers/annotations/schemas.py index 42af48d61b629..72edcc10d00f6 100644 --- a/superset/annotation_layers/annotations/schemas.py +++ b/superset/annotation_layers/annotations/schemas.py @@ -51,8 +51,8 @@ def validate_json(value: Union[bytes, bytearray, str]) -> None: try: utils.validate_json(value) - except SupersetException: - raise ValidationError("JSON not valid") + except SupersetException as ex: + raise ValidationError("JSON not valid") from ex class AnnotationPostSchema(Schema): diff --git a/superset/annotation_layers/commands/bulk_delete.py b/superset/annotation_layers/commands/bulk_delete.py index 148bdd0bd2d61..a828047fdda03 100644 --- a/superset/annotation_layers/commands/bulk_delete.py +++ b/superset/annotation_layers/commands/bulk_delete.py @@ -45,7 +45,7 @@ def run(self) -> None: return None except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise AnnotationLayerBulkDeleteFailedError() + raise AnnotationLayerBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists diff --git a/superset/annotation_layers/commands/create.py b/superset/annotation_layers/commands/create.py index c62592194938c..5e26bc49d4ae1 100644 --- a/superset/annotation_layers/commands/create.py +++ b/superset/annotation_layers/commands/create.py @@ -44,7 +44,7 @@ def run(self) -> Model: annotation_layer = AnnotationLayerDAO.create(self._properties) except DAOCreateFailedError as ex: logger.exception(ex.exception) - raise AnnotationLayerCreateFailedError() + raise AnnotationLayerCreateFailedError() from ex return annotation_layer def validate(self) -> None: diff --git a/superset/annotation_layers/commands/delete.py b/superset/annotation_layers/commands/delete.py index dd9b2c476e3c5..c439542b24d96 100644 --- a/superset/annotation_layers/commands/delete.py +++ b/superset/annotation_layers/commands/delete.py @@ -45,7 +45,7 @@ def run(self) -> Model: annotation_layer = AnnotationLayerDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise AnnotationLayerDeleteFailedError() + raise AnnotationLayerDeleteFailedError() from ex return annotation_layer def validate(self) -> None: diff --git a/superset/annotation_layers/commands/update.py b/superset/annotation_layers/commands/update.py index d5625ccb4da2f..7e8f6d5bd7bb8 100644 --- a/superset/annotation_layers/commands/update.py +++ b/superset/annotation_layers/commands/update.py @@ -48,7 +48,7 @@ def run(self) -> Model: annotation_layer = AnnotationLayerDAO.update(self._model, self._properties) except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise AnnotationLayerUpdateFailedError() + raise AnnotationLayerUpdateFailedError() from ex return annotation_layer def validate(self) -> None: diff --git a/superset/annotation_layers/dao.py b/superset/annotation_layers/dao.py index 9c848e59a46df..0ca19e270091d 100644 --- a/superset/annotation_layers/dao.py +++ b/superset/annotation_layers/dao.py @@ -41,10 +41,10 @@ def bulk_delete( ).delete(synchronize_session="fetch") if commit: db.session.commit() - except SQLAlchemyError: + except SQLAlchemyError as ex: if commit: db.session.rollback() - raise DAODeleteFailedError() + raise DAODeleteFailedError() from ex @staticmethod def has_annotations(model_id: Union[int, List[int]]) -> bool: diff --git a/superset/charts/commands/bulk_delete.py b/superset/charts/commands/bulk_delete.py index 463f17bc07fc1..26a3fce9e41c4 100644 --- a/superset/charts/commands/bulk_delete.py +++ b/superset/charts/commands/bulk_delete.py @@ -49,7 +49,7 @@ def run(self) -> None: ChartDAO.bulk_delete(self._models) except DeleteFailedError as ex: logger.exception(ex.exception) - raise ChartBulkDeleteFailedError() + raise ChartBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -67,5 +67,5 @@ def validate(self) -> None: for model in self._models: try: check_ownership(model) - except SupersetSecurityException: - raise ChartForbiddenError() + except SupersetSecurityException as ex: + raise ChartForbiddenError() from ex diff --git a/superset/charts/commands/create.py b/superset/charts/commands/create.py index a393c68111f44..36dca581a784c 100644 --- a/superset/charts/commands/create.py +++ b/superset/charts/commands/create.py @@ -49,7 +49,7 @@ def run(self) -> Model: chart = ChartDAO.create(self._properties) except DAOCreateFailedError as ex: logger.exception(ex.exception) - raise ChartCreateFailedError() + raise ChartCreateFailedError() from ex return chart def validate(self) -> None: diff --git a/superset/charts/commands/data.py b/superset/charts/commands/data.py index 1a383827cc1d1..619244c239ada 100644 --- a/superset/charts/commands/data.py +++ b/superset/charts/commands/data.py @@ -50,8 +50,8 @@ def run(self, **kwargs: Any) -> Dict[str, Any]: payload = self._query_context.get_payload( cache_query_context=cache_query_context, force_cached=force_cached ) - except CacheLoadError as exc: - raise ChartDataCacheLoadError(exc.message) + except CacheLoadError as ex: + raise ChartDataCacheLoadError(ex.message) from ex # TODO: QueryContext should support SIP-40 style errors for query in payload["queries"]: @@ -77,8 +77,8 @@ def set_query_context(self, form_data: Dict[str, Any]) -> QueryContext: self._form_data = form_data try: self._query_context = ChartDataQueryContextSchema().load(self._form_data) - except KeyError: - raise ValidationError("Request is incorrect") + except KeyError as ex: + raise ValidationError("Request is incorrect") from ex except ValidationError as error: raise error diff --git a/superset/charts/commands/delete.py b/superset/charts/commands/delete.py index 5b33a5041d411..faf72c5ef7b97 100644 --- a/superset/charts/commands/delete.py +++ b/superset/charts/commands/delete.py @@ -52,7 +52,7 @@ def run(self) -> Model: chart = ChartDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise ChartDeleteFailedError() + raise ChartDeleteFailedError() from ex return chart def validate(self) -> None: @@ -70,5 +70,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise ChartForbiddenError() + except SupersetSecurityException as ex: + raise ChartForbiddenError() from ex diff --git a/superset/charts/commands/update.py b/superset/charts/commands/update.py index 449c67da24ccd..b09845512c0c4 100644 --- a/superset/charts/commands/update.py +++ b/superset/charts/commands/update.py @@ -64,7 +64,7 @@ def run(self) -> Model: chart = ChartDAO.update(self._model, self._properties) except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise ChartUpdateFailedError() + raise ChartUpdateFailedError() from ex return chart def validate(self) -> None: @@ -89,8 +89,8 @@ def validate(self) -> None: if not is_query_context_update(self._properties): try: check_ownership(self._model) - except SupersetSecurityException: - raise ChartForbiddenError() + except SupersetSecurityException as ex: + raise ChartForbiddenError() from ex # Validate/Populate datasource if datasource_id is not None: diff --git a/superset/commands/importers/v1/__init__.py b/superset/commands/importers/v1/__init__.py index b9ea24414785f..0286735de6a01 100644 --- a/superset/commands/importers/v1/__init__.py +++ b/superset/commands/importers/v1/__init__.py @@ -66,9 +66,9 @@ def run(self) -> None: try: self._import(db.session, self._configs, self.overwrite) db.session.commit() - except Exception: + except Exception as ex: db.session.rollback() - raise self.import_error() + raise self.import_error() from ex # pylint: disable=too-many-branches def validate(self) -> None: diff --git a/superset/commands/importers/v1/examples.py b/superset/commands/importers/v1/examples.py index 03ffd2c5dcdeb..7091f88419e8e 100644 --- a/superset/commands/importers/v1/examples.py +++ b/superset/commands/importers/v1/examples.py @@ -72,9 +72,9 @@ def run(self) -> None: try: self._import(db.session, self._configs, self.overwrite, self.force_data) db.session.commit() - except Exception: + except Exception as ex: db.session.rollback() - raise self.import_error() + raise self.import_error() from ex @classmethod def _get_uuids(cls) -> Set[str]: diff --git a/superset/commands/importers/v1/utils.py b/superset/commands/importers/v1/utils.py index b071678a078d4..15bec8278ca75 100644 --- a/superset/commands/importers/v1/utils.py +++ b/superset/commands/importers/v1/utils.py @@ -47,9 +47,9 @@ def load_yaml(file_name: str, content: str) -> Dict[str, Any]: """Try to load a YAML file""" try: return yaml.safe_load(content) - except yaml.parser.ParserError: + except yaml.parser.ParserError as ex: logger.exception("Invalid YAML in %s", file_name) - raise ValidationError({file_name: "Not a valid YAML file"}) + raise ValidationError({file_name: "Not a valid YAML file"}) from ex def load_metadata(contents: Dict[str, str]) -> Dict[str, str]: @@ -63,15 +63,15 @@ def load_metadata(contents: Dict[str, str]) -> Dict[str, str]: metadata = load_yaml(METADATA_FILE_NAME, contents[METADATA_FILE_NAME]) try: MetadataSchema().load(metadata) - except ValidationError as exc: + except ValidationError as ex: # if the version doesn't match raise an exception so that the # dispatcher can try a different command version - if "version" in exc.messages: - raise IncorrectVersionError(exc.messages["version"][0]) + if "version" in ex.messages: + raise IncorrectVersionError(ex.messages["version"][0]) from ex # otherwise we raise the validation error - exc.messages = {METADATA_FILE_NAME: exc.messages} - raise exc + ex.messages = {METADATA_FILE_NAME: ex.messages} + raise ex return metadata diff --git a/superset/commands/utils.py b/superset/commands/utils.py index 0cecb2e15d35b..c656ce304036e 100644 --- a/superset/commands/utils.py +++ b/superset/commands/utils.py @@ -76,5 +76,5 @@ def get_datasource_by_id(datasource_id: int, datasource_type: str) -> BaseDataso return ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session ) - except DatasetNotFoundError: - raise DatasourceNotFoundValidationError() + except DatasetNotFoundError as ex: + raise DatasourceNotFoundValidationError() from ex diff --git a/superset/common/query_context.py b/superset/common/query_context.py index 32f3c557886de..566b01c8613be 100644 --- a/superset/common/query_context.py +++ b/superset/common/query_context.py @@ -138,7 +138,7 @@ def processing_time_offsets( # pylint: disable=too-many-locals ) query_object_clone.to_dttm = get_past_or_future(offset, outer_to_dttm) except ValueError as ex: - raise QueryObjectValidationError(str(ex)) + raise QueryObjectValidationError(str(ex)) from ex # make sure subquery use main query where clause query_object_clone.inner_from_dttm = outer_from_dttm query_object_clone.inner_to_dttm = outer_to_dttm @@ -417,7 +417,7 @@ def get_viz_annotation_data( payload = viz_obj.get_payload() return payload["data"] except SupersetException as ex: - raise QueryObjectValidationError(error_msg_from_exception(ex)) + raise QueryObjectValidationError(error_msg_from_exception(ex)) from ex def get_annotation_data(self, query_obj: QueryObject) -> Dict[str, Any]: """ diff --git a/superset/connectors/druid/views.py b/superset/connectors/druid/views.py index 5454a41d34dcf..eca14d481cf4e 100644 --- a/superset/connectors/druid/views.py +++ b/superset/connectors/druid/views.py @@ -127,7 +127,7 @@ def pre_update(self, item: "DruidColumnInlineView") -> None: try: dimension_spec = json.loads(item.dimension_spec_json) except ValueError as ex: - raise ValueError("Invalid Dimension Spec JSON: " + str(ex)) + raise ValueError("Invalid Dimension Spec JSON: " + str(ex)) from ex if not isinstance(dimension_spec, dict): raise ValueError("Dimension Spec must be a JSON object") if "outputName" not in dimension_spec: diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index c28b44eceea07..fd43010d78d0a 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -719,7 +719,7 @@ def get_fetch_values_predicate(self) -> TextClause: "Error in jinja expression in fetch values predicate: %(msg)s", msg=ex.message, ) - ) + ) from ex def values_for_column(self, column_name: str, limit: int = 10000) -> List[Any]: """Runs query against sqla to retrieve some @@ -818,7 +818,7 @@ def get_rendered_sql( "Error while rendering virtual dataset query: %(msg)s", msg=ex.message, ) - ) + ) from ex sql = sqlparse.format(sql.strip("\t\r\n; "), strip_comments=True) if not sql: raise QueryObjectValidationError(_("Virtual dataset query cannot be empty")) @@ -929,7 +929,7 @@ def _get_sqla_row_level_filters( except TemplateError as ex: raise QueryObjectValidationError( _("Error in jinja expression in RLS filters: %(msg)s", msg=ex.message,) - ) + ) from ex def get_sqla_query( # pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements self, @@ -1252,7 +1252,7 @@ def get_sqla_query( # pylint: disable=too-many-arguments,too-many-locals,too-ma "Error in jinja expression in WHERE clause: %(msg)s", msg=ex.message, ) - ) + ) from ex where_clause_and += [sa.text("({})".format(where))] having = extras.get("having") if having: @@ -1264,7 +1264,7 @@ def get_sqla_query( # pylint: disable=too-many-arguments,too-many-locals,too-ma "Error in jinja expression in HAVING clause: %(msg)s", msg=ex.message, ) - ) + ) from ex having_clause_and += [sa.text("({})".format(having))] if apply_fetch_values_predicate and self.fetch_values_predicate: qry = qry.where(self.get_fetch_values_predicate()) diff --git a/superset/connectors/sqla/utils.py b/superset/connectors/sqla/utils.py index 1ee1fc1408949..a9b62030086a6 100644 --- a/superset/connectors/sqla/utils.py +++ b/superset/connectors/sqla/utils.py @@ -110,6 +110,6 @@ def get_virtual_table_metadata(dataset: "SqlaTable") -> List[Dict[str, str]]: result = db_engine_spec.fetch_data(cursor, limit=1) result_set = SupersetResultSet(result, cursor.description, db_engine_spec) cols = result_set.columns - except Exception as exc: - raise SupersetGenericDBErrorException(message=str(exc)) + except Exception as ex: + raise SupersetGenericDBErrorException(message=str(ex)) from ex return cols diff --git a/superset/css_templates/commands/bulk_delete.py b/superset/css_templates/commands/bulk_delete.py index 40b2e800cdc85..839dbd26aee5a 100644 --- a/superset/css_templates/commands/bulk_delete.py +++ b/superset/css_templates/commands/bulk_delete.py @@ -44,7 +44,7 @@ def run(self) -> None: return None except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise CssTemplateBulkDeleteFailedError() + raise CssTemplateBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists diff --git a/superset/css_templates/dao.py b/superset/css_templates/dao.py index 8f9d36be3df70..1862fb7aafd97 100644 --- a/superset/css_templates/dao.py +++ b/superset/css_templates/dao.py @@ -39,7 +39,7 @@ def bulk_delete(models: Optional[List[CssTemplate]], commit: bool = True) -> Non ) if commit: db.session.commit() - except SQLAlchemyError: + except SQLAlchemyError as ex: if commit: db.session.rollback() - raise DAODeleteFailedError() + raise DAODeleteFailedError() from ex diff --git a/superset/dao/base.py b/superset/dao/base.py index 0cd0facf7e378..79ece40c93374 100644 --- a/superset/dao/base.py +++ b/superset/dao/base.py @@ -106,7 +106,7 @@ def create(cls, properties: Dict[str, Any], commit: bool = True) -> Model: db.session.commit() except SQLAlchemyError as ex: # pragma: no cover db.session.rollback() - raise DAOCreateFailedError(exception=ex) + raise DAOCreateFailedError(exception=ex) from ex return model @classmethod @@ -125,7 +125,7 @@ def update( db.session.commit() except SQLAlchemyError as ex: # pragma: no cover db.session.rollback() - raise DAOUpdateFailedError(exception=ex) + raise DAOUpdateFailedError(exception=ex) from ex return model @classmethod @@ -140,5 +140,5 @@ def delete(cls, model: Model, commit: bool = True) -> Model: db.session.commit() except SQLAlchemyError as ex: # pragma: no cover db.session.rollback() - raise DAODeleteFailedError(exception=ex) + raise DAODeleteFailedError(exception=ex) from ex return model diff --git a/superset/dashboards/commands/bulk_delete.py b/superset/dashboards/commands/bulk_delete.py index 27787cc61bf1f..958dea27d3915 100644 --- a/superset/dashboards/commands/bulk_delete.py +++ b/superset/dashboards/commands/bulk_delete.py @@ -50,7 +50,7 @@ def run(self) -> None: return None except DeleteFailedError as ex: logger.exception(ex.exception) - raise DashboardBulkDeleteFailedError() + raise DashboardBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -68,5 +68,5 @@ def validate(self) -> None: for model in self._models: try: check_ownership(model) - except SupersetSecurityException: - raise DashboardForbiddenError() + except SupersetSecurityException as ex: + raise DashboardForbiddenError() from ex diff --git a/superset/dashboards/commands/create.py b/superset/dashboards/commands/create.py index de136d20e1b5b..91f7e90bac56b 100644 --- a/superset/dashboards/commands/create.py +++ b/superset/dashboards/commands/create.py @@ -46,7 +46,7 @@ def run(self) -> Model: dashboard = DashboardDAO.update_charts_owners(dashboard, commit=True) except DAOCreateFailedError as ex: logger.exception(ex.exception) - raise DashboardCreateFailedError() + raise DashboardCreateFailedError() from ex return dashboard def validate(self) -> None: diff --git a/superset/dashboards/commands/delete.py b/superset/dashboards/commands/delete.py index 795288a84376f..67f683a1c1542 100644 --- a/superset/dashboards/commands/delete.py +++ b/superset/dashboards/commands/delete.py @@ -50,7 +50,7 @@ def run(self) -> Model: dashboard = DashboardDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise DashboardDeleteFailedError() + raise DashboardDeleteFailedError() from ex return dashboard def validate(self) -> None: @@ -68,5 +68,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DashboardForbiddenError() + except SupersetSecurityException as ex: + raise DashboardForbiddenError() from ex diff --git a/superset/dashboards/commands/update.py b/superset/dashboards/commands/update.py index 877c712fea838..c22f4a35fbd2d 100644 --- a/superset/dashboards/commands/update.py +++ b/superset/dashboards/commands/update.py @@ -53,7 +53,7 @@ def run(self) -> Model: dashboard = DashboardDAO.update_charts_owners(dashboard, commit=True) except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise DashboardUpdateFailedError() + raise DashboardUpdateFailedError() from ex return dashboard def validate(self) -> None: @@ -69,8 +69,8 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DashboardForbiddenError() + except SupersetSecurityException as ex: + raise DashboardForbiddenError() from ex # Validate slug uniqueness if not DashboardDAO.validate_update_slug_uniqueness(self._model_id, slug): diff --git a/superset/dashboards/schemas.py b/superset/dashboards/schemas.py index 00888b38c6e97..e577e9f19caf4 100644 --- a/superset/dashboards/schemas.py +++ b/superset/dashboards/schemas.py @@ -89,8 +89,8 @@ def validate_json(value: Union[bytes, bytearray, str]) -> None: try: utils.validate_json(value) - except SupersetException: - raise ValidationError("JSON not valid") + except SupersetException as ex: + raise ValidationError("JSON not valid") from ex def validate_json_metadata(value: Union[bytes, bytearray, str]) -> None: @@ -98,8 +98,8 @@ def validate_json_metadata(value: Union[bytes, bytearray, str]) -> None: return try: value_obj = json.loads(value) - except json.decoder.JSONDecodeError: - raise ValidationError("JSON not valid") + except json.decoder.JSONDecodeError as ex: + raise ValidationError("JSON not valid") from ex errors = DashboardJSONMetadataSchema().validate(value_obj, partial=False) if errors: raise ValidationError(errors) diff --git a/superset/databases/api.py b/superset/databases/api.py index 31be745586bd0..e604c4a4c4e6a 100644 --- a/superset/databases/api.py +++ b/superset/databases/api.py @@ -1014,7 +1014,7 @@ def validate_parameters( # pylint: disable=too-many-return-statements try: payload = DatabaseValidateParametersSchema().load(request.json) - except ValidationError as error: + except ValidationError as ex: errors = [ SupersetError( message="\n".join(messages), @@ -1022,9 +1022,9 @@ def validate_parameters( # pylint: disable=too-many-return-statements level=ErrorLevel.ERROR, extra={"invalid": [attribute]}, ) - for attribute, messages in error.messages.items() + for attribute, messages in ex.messages.items() ] - raise InvalidParametersError(errors) + raise InvalidParametersError(errors) from ex command = ValidateDatabaseParametersCommand(g.user, payload) command.run() diff --git a/superset/databases/commands/create.py b/superset/databases/commands/create.py index e4acf26b5c275..8e1bb1eed7798 100644 --- a/superset/databases/commands/create.py +++ b/superset/databases/commands/create.py @@ -53,7 +53,7 @@ def run(self) -> Model: action=f"db_creation_failed.{ex.__class__.__name__}", engine=self._properties.get("sqlalchemy_uri", "").split(":")[0], ) - raise DatabaseConnectionFailedError() + raise DatabaseConnectionFailedError() from ex try: database = DatabaseDAO.create(self._properties, commit=False) @@ -73,7 +73,7 @@ def run(self) -> Model: action=f"db_creation_failed.{ex.__class__.__name__}", engine=database.db_engine_spec.__name__, ) - raise DatabaseCreateFailedError() + raise DatabaseCreateFailedError() from ex return database def validate(self) -> None: diff --git a/superset/databases/commands/delete.py b/superset/databases/commands/delete.py index 5f002dbfb36dd..61bd7ad0a575d 100644 --- a/superset/databases/commands/delete.py +++ b/superset/databases/commands/delete.py @@ -48,7 +48,7 @@ def run(self) -> Model: database = DatabaseDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise DatabaseDeleteFailedError() + raise DatabaseDeleteFailedError() from ex return database def validate(self) -> None: diff --git a/superset/databases/commands/test_connection.py b/superset/databases/commands/test_connection.py index 3b3a8e41f6703..2b5b0b8d2cbf2 100644 --- a/superset/databases/commands/test_connection.py +++ b/superset/databases/commands/test_connection.py @@ -95,7 +95,7 @@ def run(self) -> None: message=_("Could not load database driver: {}").format( database.db_engine_spec.__name__ ), - ) + ) from ex except DBAPIError as ex: event_logger.log_with_context( action=f"test_connection_error.{ex.__class__.__name__}", @@ -103,20 +103,20 @@ def run(self) -> None: ) # check for custom errors (wrong username, wrong password, etc) errors = database.db_engine_spec.extract_errors(ex, context) - raise DatabaseTestConnectionFailedError(errors) + raise DatabaseTestConnectionFailedError(errors) from ex except SupersetSecurityException as ex: event_logger.log_with_context( action=f"test_connection_error.{ex.__class__.__name__}", engine=database.db_engine_spec.__name__, ) - raise DatabaseSecurityUnsafeError(message=str(ex)) + raise DatabaseSecurityUnsafeError(message=str(ex)) from ex except Exception as ex: # pylint: disable=broad-except event_logger.log_with_context( action=f"test_connection_error.{ex.__class__.__name__}", engine=database.db_engine_spec.__name__, ) errors = database.db_engine_spec.extract_errors(ex, context) - raise DatabaseTestConnectionUnexpectedError(errors) + raise DatabaseTestConnectionUnexpectedError(errors) from ex def validate(self) -> None: database_name = self._properties.get("database_name") diff --git a/superset/databases/commands/update.py b/superset/databases/commands/update.py index 7c48e743aedb8..db1741c32bb5b 100644 --- a/superset/databases/commands/update.py +++ b/superset/databases/commands/update.py @@ -56,7 +56,7 @@ def run(self) -> Model: schemas = database.get_all_schema_names() except Exception as ex: db.session.rollback() - raise DatabaseConnectionFailedError() + raise DatabaseConnectionFailedError() from ex for schema in schemas: security_manager.add_permission_view_menu( "schema_access", security_manager.get_schema_perm(database, schema) @@ -65,7 +65,7 @@ def run(self) -> Model: except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise DatabaseUpdateFailedError() + raise DatabaseUpdateFailedError() from ex return database def validate(self) -> None: diff --git a/superset/databases/commands/validate.py b/superset/databases/commands/validate.py index fcbff1fed70fb..5f6e1c7726d64 100644 --- a/superset/databases/commands/validate.py +++ b/superset/databases/commands/validate.py @@ -126,7 +126,7 @@ def run(self) -> None: "database": url.database, } errors = database.db_engine_spec.extract_errors(ex, context) - raise DatabaseTestConnectionFailedError(errors) + raise DatabaseTestConnectionFailedError(errors) from ex if not alive: raise DatabaseOfflineError( diff --git a/superset/databases/schemas.py b/superset/databases/schemas.py index b0dfc2f9aad76..43ef975d42092 100644 --- a/superset/databases/schemas.py +++ b/superset/databases/schemas.py @@ -142,7 +142,7 @@ def sqlalchemy_uri_validator(value: str) -> str: """ try: uri = make_url(value.strip()) - except (ArgumentError, AttributeError, ValueError): + except (ArgumentError, AttributeError, ValueError) as ex: raise ValidationError( [ _( @@ -150,12 +150,12 @@ def sqlalchemy_uri_validator(value: str) -> str: "driver://user:password@database-host/database-name" ) ] - ) + ) from ex if current_app.config.get("PREVENT_UNSAFE_DB_CONNECTIONS", True): try: check_sqlalchemy_uri(uri) except SupersetSecurityException as ex: - raise ValidationError([str(ex)]) + raise ValidationError([str(ex)]) from ex return value @@ -166,8 +166,8 @@ def server_cert_validator(value: str) -> str: if value: try: parse_ssl_cert(value) - except CertificateException: - raise ValidationError([_("Invalid certificate")]) + except CertificateException as ex: + raise ValidationError([_("Invalid certificate")]) from ex return value @@ -181,7 +181,7 @@ def encrypted_extra_validator(value: str) -> str: except json.JSONDecodeError as ex: raise ValidationError( [_("Field cannot be decoded by JSON. %(msg)s", msg=str(ex))] - ) + ) from ex return value @@ -196,7 +196,7 @@ def extra_validator(value: str) -> str: except json.JSONDecodeError as ex: raise ValidationError( [_("Field cannot be decoded by JSON. %(msg)s", msg=str(ex))] - ) + ) from ex else: metadata_signature = inspect.signature(MetaData) for key in extra_.get("metadata_params", {}): diff --git a/superset/datasets/columns/commands/delete.py b/superset/datasets/columns/commands/delete.py index 1076c00909404..f5914af5277ff 100644 --- a/superset/datasets/columns/commands/delete.py +++ b/superset/datasets/columns/commands/delete.py @@ -51,7 +51,7 @@ def run(self) -> Model: return column except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise DatasetColumnDeleteFailedError() + raise DatasetColumnDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -61,5 +61,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DatasetColumnForbiddenError() + except SupersetSecurityException as ex: + raise DatasetColumnForbiddenError() from ex diff --git a/superset/datasets/commands/bulk_delete.py b/superset/datasets/commands/bulk_delete.py index 0ba6b4e767f1b..13608eda810c9 100644 --- a/superset/datasets/commands/bulk_delete.py +++ b/superset/datasets/commands/bulk_delete.py @@ -74,7 +74,7 @@ def run(self) -> None: return None except DeleteFailedError as ex: logger.exception(ex.exception) - raise DatasetBulkDeleteFailedError() + raise DatasetBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -85,5 +85,5 @@ def validate(self) -> None: for model in self._models: try: check_ownership(model) - except SupersetSecurityException: - raise DatasetForbiddenError() + except SupersetSecurityException as ex: + raise DatasetForbiddenError() from ex diff --git a/superset/datasets/commands/create.py b/superset/datasets/commands/create.py index ca6bf8faed73a..0bf403ebfbcdb 100644 --- a/superset/datasets/commands/create.py +++ b/superset/datasets/commands/create.py @@ -62,7 +62,7 @@ def run(self) -> Model: except (SQLAlchemyError, DAOCreateFailedError) as ex: logger.warning(ex, exc_info=True) db.session.rollback() - raise DatasetCreateFailedError() + raise DatasetCreateFailedError() from ex return dataset def validate(self) -> None: diff --git a/superset/datasets/commands/delete.py b/superset/datasets/commands/delete.py index 028df423e44ae..a9e5a0ab5aba6 100644 --- a/superset/datasets/commands/delete.py +++ b/superset/datasets/commands/delete.py @@ -75,7 +75,7 @@ def run(self) -> Model: except (SQLAlchemyError, DAODeleteFailedError) as ex: logger.exception(ex) db.session.rollback() - raise DatasetDeleteFailedError() + raise DatasetDeleteFailedError() from ex return dataset def validate(self) -> None: @@ -86,5 +86,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DatasetForbiddenError() + except SupersetSecurityException as ex: + raise DatasetForbiddenError() from ex diff --git a/superset/datasets/commands/importers/v0.py b/superset/datasets/commands/importers/v0.py index a19e9ae05bf5e..1508298a23e88 100644 --- a/superset/datasets/commands/importers/v0.py +++ b/superset/datasets/commands/importers/v0.py @@ -322,9 +322,11 @@ def validate(self) -> None: for file_name, content in self.contents.items(): try: config = yaml.safe_load(content) - except yaml.parser.ParserError: + except yaml.parser.ParserError as ex: logger.exception("Invalid YAML file") - raise IncorrectVersionError(f"{file_name} is not a valid YAML file") + raise IncorrectVersionError( + f"{file_name} is not a valid YAML file" + ) from ex # CLI export if isinstance(config, dict): diff --git a/superset/datasets/commands/refresh.py b/superset/datasets/commands/refresh.py index 22869570bd9fd..962ffb4109021 100644 --- a/superset/datasets/commands/refresh.py +++ b/superset/datasets/commands/refresh.py @@ -48,7 +48,7 @@ def run(self) -> Model: return self._model except Exception as ex: logger.exception(ex) - raise DatasetRefreshFailedError() + raise DatasetRefreshFailedError() from ex raise DatasetRefreshFailedError() def validate(self) -> None: @@ -59,5 +59,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DatasetForbiddenError() + except SupersetSecurityException as ex: + raise DatasetForbiddenError() from ex diff --git a/superset/datasets/commands/update.py b/superset/datasets/commands/update.py index 1a8237686900c..c9bf8500c9297 100644 --- a/superset/datasets/commands/update.py +++ b/superset/datasets/commands/update.py @@ -72,7 +72,7 @@ def run(self) -> Model: return dataset except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise DatasetUpdateFailedError() + raise DatasetUpdateFailedError() from ex raise DatasetUpdateFailedError() def validate(self) -> None: @@ -85,8 +85,8 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DatasetForbiddenError() + except SupersetSecurityException as ex: + raise DatasetForbiddenError() from ex database_id = self._properties.get("database", None) table_name = self._properties.get("table_name", None) diff --git a/superset/datasets/metrics/commands/delete.py b/superset/datasets/metrics/commands/delete.py index e6f68dc981212..cb3f1e0bea1e8 100644 --- a/superset/datasets/metrics/commands/delete.py +++ b/superset/datasets/metrics/commands/delete.py @@ -51,7 +51,7 @@ def run(self) -> Model: return column except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise DatasetMetricDeleteFailedError() + raise DatasetMetricDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -61,5 +61,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise DatasetMetricForbiddenError() + except SupersetSecurityException as ex: + raise DatasetMetricForbiddenError() from ex diff --git a/superset/db_engine_specs/bigquery.py b/superset/db_engine_specs/bigquery.py index 99dfdb7387d61..734984499fcea 100644 --- a/superset/db_engine_specs/bigquery.py +++ b/superset/db_engine_specs/bigquery.py @@ -327,12 +327,12 @@ def df_to_sql( # pylint: disable=import-outside-toplevel import pandas_gbq from google.oauth2 import service_account - except ImportError: + except ImportError as ex: raise Exception( "Could not import libraries `pandas_gbq` or `google.oauth2`, which are " "required to be installed in your environment in order " "to upload data to BigQuery" - ) + ) from ex if not table.schema: raise Exception("The table schema must be defined") diff --git a/superset/db_engine_specs/druid.py b/superset/db_engine_specs/druid.py index ef699e43d5d97..faccb002060f1 100644 --- a/superset/db_engine_specs/druid.py +++ b/superset/db_engine_specs/druid.py @@ -79,8 +79,8 @@ def get_extra_params(database: "Database") -> Dict[str, Any]: """ try: extra = json.loads(database.extra or "{}") - except json.JSONDecodeError: - raise SupersetException("Unable to parse database extras") + except json.JSONDecodeError as ex: + raise SupersetException("Unable to parse database extras") from ex if database.server_cert: engine_params = extra.get("engine_params", {}) diff --git a/superset/db_engine_specs/postgres.py b/superset/db_engine_specs/postgres.py index 31b2520b26e6f..4d1936310d4d7 100644 --- a/superset/db_engine_specs/postgres.py +++ b/superset/db_engine_specs/postgres.py @@ -262,8 +262,8 @@ def get_extra_params(database: "Database") -> Dict[str, Any]: """ try: extra = json.loads(database.extra or "{}") - except json.JSONDecodeError: - raise SupersetException("Unable to parse database extras") + except json.JSONDecodeError as ex: + raise SupersetException("Unable to parse database extras") from ex if database.server_cert: engine_params = extra.get("engine_params", {}) diff --git a/superset/db_engines/hive.py b/superset/db_engines/hive.py index b5f5cad5717c5..37fe50f5e21e6 100644 --- a/superset/db_engines/hive.py +++ b/superset/db_engines/hive.py @@ -46,9 +46,9 @@ def fetch_logs( logs = self._connection.client.GetLog(req).log return logs # raised if Hive is used - except (ttypes.TApplicationException, Thrift.TApplicationException): + except (ttypes.TApplicationException, Thrift.TApplicationException) as ex: if self._state == self._STATE_NONE: - raise hive.ProgrammingError("No query yet") + raise hive.ProgrammingError("No query yet") from ex logs = [] while True: req = ttypes.TFetchResultsReq( diff --git a/superset/jinja_context.py b/superset/jinja_context.py index ff56fc9b24331..907ba99a8c856 100644 --- a/superset/jinja_context.py +++ b/superset/jinja_context.py @@ -333,10 +333,10 @@ def safe_proxy(func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: if value_type in COLLECTION_TYPES: try: return_value = json.loads(json.dumps(return_value)) - except TypeError: + except TypeError as ex: raise SupersetTemplateException( _("Unsupported return value for method %(name)s", name=func.__name__,) - ) + ) from ex return return_value @@ -357,10 +357,10 @@ def validate_context_types(context: Dict[str, Any]) -> Dict[str, Any]: if arg_type in COLLECTION_TYPES: try: context[key] = json.loads(json.dumps(context[key])) - except TypeError: + except TypeError as ex: raise SupersetTemplateException( _("Unsupported template value for key %(key)s", key=key) - ) + ) from ex return context diff --git a/superset/models/tags.py b/superset/models/tags.py index 86fc411222fce..528206e672f62 100644 --- a/superset/models/tags.py +++ b/superset/models/tags.py @@ -106,8 +106,8 @@ def get_object_type(class_name: str) -> ObjectTypes: } try: return mapping[class_name.lower()] - except KeyError: - raise Exception("No mapping found for {0}".format(class_name)) + except KeyError as ex: + raise Exception("No mapping found for {0}".format(class_name)) from ex class ObjectUpdater: diff --git a/superset/queries/saved_queries/commands/bulk_delete.py b/superset/queries/saved_queries/commands/bulk_delete.py index cf021442fbfcc..0d199378c7585 100644 --- a/superset/queries/saved_queries/commands/bulk_delete.py +++ b/superset/queries/saved_queries/commands/bulk_delete.py @@ -44,7 +44,7 @@ def run(self) -> None: return None except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise SavedQueryBulkDeleteFailedError() + raise SavedQueryBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists diff --git a/superset/queries/saved_queries/dao.py b/superset/queries/saved_queries/dao.py index cd20fe60de583..48dc67d069db8 100644 --- a/superset/queries/saved_queries/dao.py +++ b/superset/queries/saved_queries/dao.py @@ -41,7 +41,7 @@ def bulk_delete(models: Optional[List[SavedQuery]], commit: bool = True) -> None ) if commit: db.session.commit() - except SQLAlchemyError: + except SQLAlchemyError as ex: if commit: db.session.rollback() - raise DAODeleteFailedError() + raise DAODeleteFailedError() from ex diff --git a/superset/reports/commands/alert.py b/superset/reports/commands/alert.py index 5dd9797055c1f..a13916f59ceb9 100644 --- a/superset/reports/commands/alert.py +++ b/superset/reports/commands/alert.py @@ -79,8 +79,8 @@ def run(self) -> bool: ] return OPERATOR_FUNCTIONS[operator](self._result, threshold) - except (KeyError, json.JSONDecodeError): - raise AlertValidatorConfigError() + except (KeyError, json.JSONDecodeError) as ex: + raise AlertValidatorConfigError() from ex def _validate_not_null(self, rows: np.recarray) -> None: self._validate_result(rows) @@ -115,8 +115,8 @@ def _validate_operator(self, rows: np.recarray) -> None: # Check if it's float or if we can convert it self._result = float(rows[0][1]) return - except (AssertionError, TypeError, ValueError): - raise AlertQueryInvalidTypeError() + except (AssertionError, TypeError, ValueError) as ex: + raise AlertQueryInvalidTypeError() from ex @property def _is_validator_not_null(self) -> bool: @@ -157,9 +157,9 @@ def _execute_query(self) -> pd.DataFrame: return df except SoftTimeLimitExceeded as ex: logger.warning("A timeout occurred while executing the alert query: %s", ex) - raise AlertQueryTimeout() + raise AlertQueryTimeout() from ex except Exception as ex: - raise AlertQueryError(message=str(ex)) + raise AlertQueryError(message=str(ex)) from ex def validate(self) -> None: """ diff --git a/superset/reports/commands/bulk_delete.py b/superset/reports/commands/bulk_delete.py index aa4898e9e55d3..4bff600d29dfa 100644 --- a/superset/reports/commands/bulk_delete.py +++ b/superset/reports/commands/bulk_delete.py @@ -47,7 +47,7 @@ def run(self) -> None: return None except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise ReportScheduleBulkDeleteFailedError() + raise ReportScheduleBulkDeleteFailedError() from ex def validate(self) -> None: # Validate/populate model exists @@ -59,5 +59,5 @@ def validate(self) -> None: for model in self._models: try: check_ownership(model) - except SupersetSecurityException: - raise ReportScheduleForbiddenError() + except SupersetSecurityException as ex: + raise ReportScheduleForbiddenError() from ex diff --git a/superset/reports/commands/create.py b/superset/reports/commands/create.py index 518a95e105e43..23ed27e89c440 100644 --- a/superset/reports/commands/create.py +++ b/superset/reports/commands/create.py @@ -51,7 +51,7 @@ def run(self) -> Model: report_schedule = ReportScheduleDAO.create(self._properties) except DAOCreateFailedError as ex: logger.exception(ex.exception) - raise ReportScheduleCreateFailedError() + raise ReportScheduleCreateFailedError() from ex return report_schedule def validate(self) -> None: diff --git a/superset/reports/commands/delete.py b/superset/reports/commands/delete.py index 8375f52c30e34..eef7a56aff79f 100644 --- a/superset/reports/commands/delete.py +++ b/superset/reports/commands/delete.py @@ -47,7 +47,7 @@ def run(self) -> Model: report_schedule = ReportScheduleDAO.delete(self._model) except DAODeleteFailedError as ex: logger.exception(ex.exception) - raise ReportScheduleDeleteFailedError() + raise ReportScheduleDeleteFailedError() from ex return report_schedule def validate(self) -> None: @@ -59,5 +59,5 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise ReportScheduleForbiddenError() + except SupersetSecurityException as ex: + raise ReportScheduleForbiddenError() from ex diff --git a/superset/reports/commands/execute.py b/superset/reports/commands/execute.py index aea2ff41c498e..065e38bc75362 100644 --- a/superset/reports/commands/execute.py +++ b/superset/reports/commands/execute.py @@ -201,13 +201,13 @@ def _get_screenshot(self) -> bytes: user = self._get_user() try: image_data = screenshot.get_screenshot(user=user) - except SoftTimeLimitExceeded: + except SoftTimeLimitExceeded as ex: logger.warning("A timeout occurred while taking a screenshot.") - raise ReportScheduleScreenshotTimeout() + raise ReportScheduleScreenshotTimeout() from ex except Exception as ex: raise ReportScheduleScreenshotFailedError( f"Failed taking a screenshot {str(ex)}" - ) + ) from ex if not image_data: raise ReportScheduleScreenshotFailedError() return image_data @@ -239,10 +239,12 @@ def _get_csv_data(self) -> bytes: try: logger.info("Getting chart from %s", url) csv_data = get_chart_csv_data(url, auth_cookies) - except SoftTimeLimitExceeded: - raise ReportScheduleCsvTimeout() + except SoftTimeLimitExceeded as ex: + raise ReportScheduleCsvTimeout() from ex except Exception as ex: - raise ReportScheduleCsvFailedError(f"Failed generating csv {str(ex)}") + raise ReportScheduleCsvFailedError( + f"Failed generating csv {str(ex)}" + ) from ex if not csv_data: raise ReportScheduleCsvFailedError() return csv_data @@ -581,7 +583,7 @@ def run(self) -> None: except CommandException as ex: raise ex except Exception as ex: - raise ReportScheduleUnexpectedError(str(ex)) + raise ReportScheduleUnexpectedError(str(ex)) from ex def validate( # pylint: disable=arguments-differ self, session: Session = None diff --git a/superset/reports/commands/update.py b/superset/reports/commands/update.py index 09809807f5856..c1dd4167908f3 100644 --- a/superset/reports/commands/update.py +++ b/superset/reports/commands/update.py @@ -55,7 +55,7 @@ def run(self) -> Model: report_schedule = ReportScheduleDAO.update(self._model, self._properties) except DAOUpdateFailedError as ex: logger.exception(ex.exception) - raise ReportScheduleUpdateFailedError() + raise ReportScheduleUpdateFailedError() from ex return report_schedule def validate(self) -> None: @@ -110,8 +110,8 @@ def validate(self) -> None: # Check ownership try: check_ownership(self._model) - except SupersetSecurityException: - raise ReportScheduleForbiddenError() + except SupersetSecurityException as ex: + raise ReportScheduleForbiddenError() from ex # Validate/Populate owner if owner_ids is None: diff --git a/superset/reports/dao.py b/superset/reports/dao.py index 697b08c1f5373..ce69ba004c470 100644 --- a/superset/reports/dao.py +++ b/superset/reports/dao.py @@ -111,7 +111,7 @@ def bulk_delete( except SQLAlchemyError as ex: if commit: db.session.rollback() - raise DAODeleteFailedError(str(ex)) + raise DAODeleteFailedError(str(ex)) from ex @staticmethod def validate_update_uniqueness( @@ -161,7 +161,7 @@ def create(cls, properties: Dict[str, Any], commit: bool = True) -> Model: return model except SQLAlchemyError as ex: db.session.rollback() - raise DAOCreateFailedError(str(ex)) + raise DAOCreateFailedError(str(ex)) from ex @classmethod def update( @@ -194,7 +194,7 @@ def update( return model except SQLAlchemyError as ex: db.session.rollback() - raise DAOCreateFailedError(str(ex)) + raise DAOCreateFailedError(str(ex)) from ex @staticmethod def find_active(session: Optional[Session] = None) -> List[ReportSchedule]: @@ -302,4 +302,4 @@ def bulk_delete_logs( except SQLAlchemyError as ex: if commit: session.rollback() - raise DAODeleteFailedError(str(ex)) + raise DAODeleteFailedError(str(ex)) from ex diff --git a/superset/reports/notifications/email.py b/superset/reports/notifications/email.py index 9a5ab29ae0285..a55824d4f8393 100644 --- a/superset/reports/notifications/email.py +++ b/superset/reports/notifications/email.py @@ -133,4 +133,4 @@ def send(self) -> None: ) logger.info("Report sent to email") except Exception as ex: - raise NotificationError(ex) + raise NotificationError(ex) from ex diff --git a/superset/reports/notifications/slack.py b/superset/reports/notifications/slack.py index 6d04b0991ac02..8d4078c92fb60 100644 --- a/superset/reports/notifications/slack.py +++ b/superset/reports/notifications/slack.py @@ -152,4 +152,4 @@ def send(self) -> None: client.chat_postMessage(channel=channel, text=body) logger.info("Report sent to slack") except SlackClientError as ex: - raise NotificationError(ex) + raise NotificationError(ex) from ex diff --git a/superset/sql_lab.py b/superset/sql_lab.py index d58124d73ddb8..d392e6c25d4cb 100644 --- a/superset/sql_lab.py +++ b/superset/sql_lab.py @@ -149,8 +149,8 @@ def get_query(query_id: int, session: Session) -> Query: """attempts to get the query and retry if it cannot""" try: return session.query(Query).filter_by(id=query_id).one() - except Exception: - raise SqlLabException("Failed at getting query") + except Exception as ex: + raise SqlLabException("Failed at getting query") from ex @celery_app.task( @@ -291,17 +291,17 @@ def execute_sql_statement( error_type=SupersetErrorType.SQLLAB_TIMEOUT_ERROR, level=ErrorLevel.ERROR, ) - ) + ) from ex except Exception as ex: # query is stopped in another thread/worker # stopping raises expected exceptions which we should skip session.refresh(query) if query.status == QueryStatus.STOPPED: - raise SqlLabQueryStoppedException() + raise SqlLabQueryStoppedException() from ex logger.error("Query %d: %s", query.id, type(ex), exc_info=True) logger.debug("Query %d: %s", query.id, ex) - raise SqlLabException(db_engine_spec.extract_error_message(ex)) + raise SqlLabException(db_engine_spec.extract_error_message(ex)) from ex logger.debug("Query %d: Fetching cursor description", query.id) cursor_description = cursor.description diff --git a/superset/utils/async_query_manager.py b/superset/utils/async_query_manager.py index 258024f7f3f6d..011564e822b52 100644 --- a/superset/utils/async_query_manager.py +++ b/superset/utils/async_query_manager.py @@ -165,9 +165,9 @@ def parse_jwt_from_request(self, req: Request) -> Dict[str, Any]: try: return self.parse_jwt(token) - except Exception as exc: - logger.warning(exc) - raise AsyncQueryTokenException("Failed to parse token") + except Exception as ex: + logger.warning(ex) + raise AsyncQueryTokenException("Failed to parse token") from ex def init_job(self, channel_id: str, user_id: Optional[str]) -> Dict[str, Any]: job_id = str(uuid.uuid4()) diff --git a/superset/utils/core.py b/superset/utils/core.py index 8e51afb9cd33c..270d740949636 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -765,7 +765,7 @@ def validate_json(obj: Union[bytes, bytearray, str]) -> None: json.loads(obj) except Exception as ex: logger.error("JSON is not valid %s", str(ex), exc_info=True) - raise SupersetException("JSON is not valid") + raise SupersetException("JSON is not valid") from ex class SigalrmTimeout: @@ -1424,8 +1424,8 @@ def parse_ssl_cert(certificate: str) -> _Certificate: return x509.load_pem_x509_certificate( certificate.encode("utf-8"), default_backend() ) - except ValueError: - raise CertificateException("Invalid certificate") + except ValueError as ex: + raise CertificateException("Invalid certificate") from ex def create_ssl_cert_file(certificate: str) -> str: diff --git a/superset/utils/date_parser.py b/superset/utils/date_parser.py index eaa7f7f98dd7f..3e742d56def1d 100644 --- a/superset/utils/date_parser.py +++ b/superset/utils/date_parser.py @@ -66,7 +66,7 @@ def parse_human_datetime(human_readable: str) -> datetime: # 0 == not parsed at all if parsed_flags == 0: logger.debug(ex) - raise TimeRangeParseFailError(human_readable) + raise TimeRangeParseFailError(human_readable) from ex # when time is not extracted, we 'reset to midnight' if parsed_flags & 2 == 0: parsed_dttm = parsed_dttm.replace(hour=0, minute=0, second=0) @@ -476,8 +476,8 @@ def datetime_eval(datetime_expression: Optional[str] = None) -> Optional[datetim if datetime_expression: try: return datetime_parser().parseString(datetime_expression)[0].eval() - except ParseException as error: - raise ValueError(error) + except ParseException as ex: + raise ValueError(ex) from ex return None diff --git a/superset/utils/pandas_postprocessing.py b/superset/utils/pandas_postprocessing.py index 1c27cf9c3666f..ad6c6afedade1 100644 --- a/superset/utils/pandas_postprocessing.py +++ b/superset/utils/pandas_postprocessing.py @@ -397,14 +397,14 @@ def rolling( # pylint: disable=too-many-arguments ) try: df_rolling = getattr(df_rolling, rolling_type)(**rolling_type_options) - except TypeError: + except TypeError as ex: raise QueryObjectValidationError( _( "Invalid options for %(rolling_type)s: %(options)s", rolling_type=rolling_type, options=rolling_type_options, ) - ) + ) from ex df = _append_columns(df, df_rolling, columns) if min_periods: df = df[min_periods:] @@ -569,8 +569,8 @@ def geohash_decode( return _append_columns( df, lonlat_df, {"latitude": latitude, "longitude": longitude} ) - except ValueError: - raise QueryObjectValidationError(_("Invalid geohash string")) + except ValueError as ex: + raise QueryObjectValidationError(_("Invalid geohash string")) from ex def geohash_encode( @@ -592,8 +592,8 @@ def geohash_encode( lambda row: geohash_lib.encode(row["latitude"], row["longitude"]), axis=1, ) return _append_columns(df, encode_df, {"geohash": geohash}) - except ValueError: - raise QueryObjectValidationError(_("Invalid longitude/latitude")) + except ValueError as ex: + raise QueryObjectValidationError(_("Invalid longitude/latitude")) from ex def geodetic_parse( @@ -634,8 +634,8 @@ def _parse_location(location: str) -> Tuple[float, float, float]: if altitude: columns["altitude"] = altitude return _append_columns(df, geodetic_df, columns) - except ValueError: - raise QueryObjectValidationError(_("Invalid geodetic string")) + except ValueError as ex: + raise QueryObjectValidationError(_("Invalid geodetic string")) from ex @validate_column_args("columns") @@ -720,8 +720,8 @@ def _prophet_fit_and_predict( # pylint: disable=too-many-arguments prophet_logger = logging.getLogger("prophet.plot") prophet_logger.setLevel(logging.CRITICAL) prophet_logger.setLevel(logging.NOTSET) - except ModuleNotFoundError: - raise QueryObjectValidationError(_("`prophet` package not installed")) + except ModuleNotFoundError as ex: + raise QueryObjectValidationError(_("`prophet` package not installed")) from ex model = Prophet( interval_width=confidence_interval, yearly_seasonality=yearly_seasonality, diff --git a/superset/utils/schema.py b/superset/utils/schema.py index 2384e2851419c..c082ae017c211 100644 --- a/superset/utils/schema.py +++ b/superset/utils/schema.py @@ -50,5 +50,5 @@ def validate_json(value: Union[bytes, bytearray, str]) -> None: """ try: utils.validate_json(value) - except SupersetException: - raise ValidationError("JSON not valid") + except SupersetException as ex: + raise ValidationError("JSON not valid") from ex diff --git a/superset/views/base.py b/superset/views/base.py index a636762c692b6..2de98b5e6b91e 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -254,7 +254,7 @@ def validate_sqlatable(table: models.SqlaTable) -> None: "database connection, schema, and " "table name, error: {}" ).format(table.name, str(ex)) - ) + ) from ex def create_table_permissions(table: models.SqlaTable) -> None: @@ -501,7 +501,7 @@ def validate_json(form: Form, field: Field) -> None: # pylint: disable=unused-a json.loads(field.data) except Exception as ex: logger.exception(ex) - raise Exception(_("json isn't valid")) + raise Exception(_("json isn't valid")) from ex class YamlExportMixin: # pylint: disable=too-few-public-methods diff --git a/superset/views/base_schemas.py b/superset/views/base_schemas.py index 65c9a3567aa9e..de39e71027624 100644 --- a/superset/views/base_schemas.py +++ b/superset/views/base_schemas.py @@ -31,8 +31,8 @@ def validate_owner(value: int) -> None: .filter_by(id=value) .one() ) - except NoResultFound: - raise ValidationError(f"User {value} does not exist") + except NoResultFound as ex: + raise ValidationError(f"User {value} does not exist") from ex class BaseSupersetSchema(Schema): diff --git a/superset/views/core.py b/superset/views/core.py index b46fa969a12da..cc03e8e928ca6 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -2040,14 +2040,14 @@ def sqllab_viz(self) -> FlaskResponse: # pylint: disable=no-self-use try: table_name = data["datasourceName"] database_id = data["dbId"] - except KeyError: + except KeyError as ex: raise SupersetGenericErrorException( __( "One or more required fields are missing in the request. Please try " "again, and if the problem persists conctact your administrator." ), status=400, - ) + ) from ex database = db.session.query(Database).get(database_id) if not database: raise SupersetErrorException( @@ -2480,7 +2480,7 @@ def _sql_json_async( # pylint: disable=too-many-arguments query.error_message = message session.commit() - raise SupersetErrorException(error) + raise SupersetErrorException(error) from ex # Update saved query with execution info from the query execution QueryDAO.update_saved_query_exec_info(query_id) @@ -2549,7 +2549,9 @@ def _sql_json_sync( raise ex except Exception as ex: # pylint: disable=broad-except logger.exception("Query %i failed unexpectedly", query.id) - raise SupersetGenericDBErrorException(utils.error_msg_from_exception(ex)) + raise SupersetGenericDBErrorException( + utils.error_msg_from_exception(ex) + ) from ex if data.get("status") == QueryStatus.FAILED: # new error payload with rich context diff --git a/superset/views/database/mixins.py b/superset/views/database/mixins.py index c415d68f376e0..2c1fb26df692f 100644 --- a/superset/views/database/mixins.py +++ b/superset/views/database/mixins.py @@ -242,7 +242,7 @@ def check_extra(self, database: Database) -> None: # pylint: disable=no-self-us except Exception as ex: raise Exception( _("Extra field cannot be decoded by JSON. %(msg)s", msg=str(ex)) - ) + ) from ex # this will check whether 'metadata_params' is configured correctly metadata_signature = inspect.signature(MetaData) @@ -266,4 +266,4 @@ def check_encrypted_extra( # pylint: disable=no-self-use except Exception as ex: raise Exception( _("Extra field cannot be decoded by JSON. %(msg)s", msg=str(ex)) - ) + ) from ex diff --git a/superset/views/database/validators.py b/superset/views/database/validators.py index a54b853b43b30..bd3b3335c582b 100644 --- a/superset/views/database/validators.py +++ b/superset/views/database/validators.py @@ -34,7 +34,7 @@ def sqlalchemy_uri_validator( """ try: make_url(uri.strip()) - except (ArgumentError, AttributeError): + except (ArgumentError, AttributeError) as ex: raise exception( [ _( @@ -45,7 +45,7 @@ def sqlalchemy_uri_validator( "

" ) ] - ) + ) from ex def schema_allows_csv_upload(database: Database, schema: Optional[str]) -> bool: diff --git a/superset/views/database/views.py b/superset/views/database/views.py index 0a0a50d81fe5c..d999853c1a1c9 100644 --- a/superset/views/database/views.py +++ b/superset/views/database/views.py @@ -65,7 +65,7 @@ def certificate_form_validator(_: _, field: StringField) -> None: try: utils.parse_ssl_cert(field.data) except CertificateException as ex: - raise ValidationError(ex.message) + raise ValidationError(ex.message) from ex def upload_stream_write(form_file_field: "FileStorage", path: str) -> None: diff --git a/superset/views/datasource/views.py b/superset/views/datasource/views.py index 448a682287939..cc3d6d202ebb1 100644 --- a/superset/views/datasource/views.py +++ b/superset/views/datasource/views.py @@ -81,8 +81,8 @@ def save(self) -> FlaskResponse: if app.config["OLD_API_CHECK_DATASET_OWNERSHIP"]: try: check_ownership(orm_datasource) - except SupersetSecurityException: - raise DatasetForbiddenError() + except SupersetSecurityException as ex: + raise DatasetForbiddenError() from ex datasource_dict["owners"] = ( db.session.query(orm_datasource.owner_class) @@ -175,6 +175,6 @@ def external_metadata_by_name(self, **kwargs: Any) -> FlaskResponse: table_name=params["table_name"], schema_name=params["schema_name"], ) - except (NoResultFound, NoSuchTableError): - raise DatasetNotFoundError + except (NoResultFound, NoSuchTableError) as ex: + raise DatasetNotFoundError() from ex return self.json_response(external_metadata) diff --git a/superset/views/schedules.py b/superset/views/schedules.py index 7924143955e7b..679973b8d1848 100644 --- a/superset/views/schedules.py +++ b/superset/views/schedules.py @@ -134,8 +134,8 @@ def pre_add(self, item: "EmailScheduleView") -> None: try: recipients = get_email_address_list(item.recipients) item.recipients = ", ".join(recipients) - except Exception: - raise SupersetException("Invalid email list") + except Exception as ex: + raise SupersetException("Invalid email list") from ex item.user = item.user or g.user if not croniter.is_valid(item.crontab): diff --git a/superset/views/utils.py b/superset/views/utils.py index 4d4bc17ab7a53..6a61f66b0e708 100644 --- a/superset/views/utils.py +++ b/superset/views/utils.py @@ -521,7 +521,7 @@ def check_datasource_perms( level=ErrorLevel.ERROR, message=str(ex), ) - ) + ) from ex if datasource_type is None: raise SupersetSecurityException( @@ -539,14 +539,14 @@ def check_datasource_perms( form_data=form_data, force=False, ) - except NoResultFound: + except NoResultFound as ex: raise SupersetSecurityException( SupersetError( error_type=SupersetErrorType.UNKNOWN_DATASOURCE_TYPE_ERROR, level=ErrorLevel.ERROR, message=_("Could not find viz object"), ) - ) + ) from ex viz_obj.raise_for_access() @@ -572,14 +572,14 @@ def check_slice_perms(_self: Any, slice_id: int) -> None: form_data=form_data, force=False, ) - except NoResultFound: + except NoResultFound as ex: raise SupersetSecurityException( SupersetError( error_type=SupersetErrorType.UNKNOWN_DATASOURCE_TYPE_ERROR, level=ErrorLevel.ERROR, message="Could not find viz object", ) - ) + ) from ex viz_obj.raise_for_access() @@ -597,8 +597,8 @@ def _deserialize_results_payload( with stats_timing("sqllab.query.results_backend_pa_deserialize", stats_logger): try: pa_table = pa.deserialize(ds_payload["data"]) - except pa.ArrowSerializationError: - raise SerializationError("Unable to deserialize table") + except pa.ArrowSerializationError as ex: + raise SerializationError("Unable to deserialize table") from ex df = result_set.SupersetResultSet.convert_table_to_df(pa_table) ds_payload["data"] = dataframe.df_to_records(df) or []