# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # pylint: disable=unused-argument, invalid-name from flask.ctx import AppContext from pytest_mock import MockFixture from superset.errors import ErrorLevel, SupersetError, SupersetErrorType class ProgrammingError(Exception): """ Dummy ProgrammingError so we don't need to import the optional gsheets. """ def test_validate_parameters_simple( mocker: MockFixture, app_context: AppContext, ) -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, GSheetsParametersType, ) parameters: GSheetsParametersType = { "credentials_info": {}, "query": {}, "table_catalog": {}, } errors = GSheetsEngineSpec.validate_parameters(parameters) assert errors == [] def test_validate_parameters_catalog( mocker: MockFixture, app_context: AppContext, ) -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, GSheetsParametersType, ) g = mocker.patch("superset.db_engine_specs.gsheets.g") g.user.email = "admin@example.com" create_engine = mocker.patch("superset.db_engine_specs.gsheets.create_engine") conn = create_engine.return_value.connect.return_value results = conn.execute.return_value results.fetchall.side_effect = [ ProgrammingError("The caller does not have permission"), [(1,)], ProgrammingError("Unsupported table: https://www.google.com/"), ] parameters: GSheetsParametersType = { "credentials_info": {}, "query": {}, "table_catalog": { "private_sheet": "https://docs.google.com/spreadsheets/d/1/edit", "public_sheet": "https://docs.google.com/spreadsheets/d/1/edit#gid=1", "not_a_sheet": "https://www.google.com/", }, } errors = GSheetsEngineSpec.validate_parameters(parameters) assert errors == [ SupersetError( message=( "Unable to connect to spreadsheet private_sheet at " "https://docs.google.com/spreadsheets/d/1/edit" ), error_type=SupersetErrorType.TABLE_DOES_NOT_EXIST_ERROR, level=ErrorLevel.WARNING, extra={ "name": "private_sheet", "url": "https://docs.google.com/spreadsheets/d/1/edit", "issue_codes": [ { "code": 1003, "message": ( "Issue 1003 - There is a syntax error in the SQL query. " "Perhaps there was a misspelling or a typo." ), }, { "code": 1005, "message": ( "Issue 1005 - The table was deleted or renamed in the " "database." ), }, ], }, ), SupersetError( message=( "Unable to connect to spreadsheet not_a_sheet at " "https://www.google.com/" ), error_type=SupersetErrorType.TABLE_DOES_NOT_EXIST_ERROR, level=ErrorLevel.WARNING, extra={ "name": "not_a_sheet", "url": "https://www.google.com/", "issue_codes": [ { "code": 1003, "message": ( "Issue 1003 - There is a syntax error in the SQL query. " "Perhaps there was a misspelling or a typo." ), }, { "code": 1005, "message": ( "Issue 1005 - The table was deleted or renamed in the " "database.", ), }, ], }, ), ] create_engine.assert_called_with( "gsheets://", service_account_info={}, subject="admin@example.com", ) def test_validate_parameters_catalog_and_credentials( mocker: MockFixture, app_context: AppContext, ) -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, GSheetsParametersType, ) g = mocker.patch("superset.db_engine_specs.gsheets.g") g.user.email = "admin@example.com" create_engine = mocker.patch("superset.db_engine_specs.gsheets.create_engine") conn = create_engine.return_value.connect.return_value results = conn.execute.return_value results.fetchall.side_effect = [ [(2,)], [(1,)], ProgrammingError("Unsupported table: https://www.google.com/"), ] parameters: GSheetsParametersType = { "credentials_info": {}, "query": {}, "table_catalog": { "private_sheet": "https://docs.google.com/spreadsheets/d/1/edit", "public_sheet": "https://docs.google.com/spreadsheets/d/1/edit#gid=1", "not_a_sheet": "https://www.google.com/", }, } errors = GSheetsEngineSpec.validate_parameters(parameters) assert errors == [ SupersetError( message=( "Unable to connect to spreadsheet not_a_sheet at " "https://www.google.com/" ), error_type=SupersetErrorType.TABLE_DOES_NOT_EXIST_ERROR, level=ErrorLevel.WARNING, extra={ "name": "not_a_sheet", "url": "https://www.google.com/", "issue_codes": [ { "code": 1003, "message": ( "Issue 1003 - There is a syntax error in the SQL query. " "Perhaps there was a misspelling or a typo." ), }, { "code": 1005, "message": ( "Issue 1005 - The table was deleted or renamed in the " "database.", ), }, ], }, ), ] create_engine.assert_called_with( "gsheets://", service_account_info={}, subject="admin@example.com", )