This is an automated email from the ASF dual-hosted git repository. hugh pushed a commit to branch 2022.39.1 in repository https://gitbox.apache.org/repos/asf/superset.git
commit 2af1000492999ec4461b816560d975dd5117855b Author: Hugh A. Miles II <[email protected]> AuthorDate: Thu Oct 6 22:57:12 2022 -0400 fix conflict with cherry 882bfb67a --- .../CRUD/data/database/DatabaseModal/index.tsx | 17 +++++++- superset/databases/schemas.py | 5 +++ superset/db_engine_specs/gsheets.py | 19 +++++++-- tests/unit_tests/db_engine_specs/test_gsheets.py | 48 ++++++++++++++++++---- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx index de5d750ebd..a2ca444752 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx @@ -569,6 +569,18 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({ // Clone DB object const dbToUpdate = JSON.parse(JSON.stringify(db || {})); + if (dbToUpdate.catalog) { + // convert catalog to fit /validate_parameters endpoint + dbToUpdate.catalog = Object.assign( + {}, + ...dbToUpdate.catalog.map((x: { name: string; value: string }) => ({ + [x.name]: x.value, + })), + ); + } else { + dbToUpdate.catalog = {}; + } + if (dbToUpdate.configuration_method === CONFIGURATION_METHOD.DYNAMIC_FORM) { // Validate DB before saving const errors = await getValidation(dbToUpdate, true); @@ -734,7 +746,10 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({ }); } - setDB({ type: ActionType.addTableCatalogSheet }); + if (database_name === 'Google Sheets') { + // only create a catalog if the DB is Google Sheets + setDB({ type: ActionType.addTableCatalogSheet }); + } }; const renderAvailableSelector = () => ( diff --git a/superset/databases/schemas.py b/superset/databases/schemas.py index 201e35cbfc..dafd1ba7fc 100644 --- a/superset/databases/schemas.py +++ b/superset/databases/schemas.py @@ -315,6 +315,11 @@ class DatabaseValidateParametersSchema(Schema): values=fields.Raw(allow_none=True), description="DB-specific parameters for configuration", ) + catalog = fields.Dict( + keys=fields.String(), + values=fields.Raw(allow_none=True), + description="Gsheets specific column for managing label to sheet urls", + ) database_name = fields.String( description=database_name_description, allow_none=True, diff --git a/superset/db_engine_specs/gsheets.py b/superset/db_engine_specs/gsheets.py index 3562e0d0b1..b42b26c3bc 100644 --- a/superset/db_engine_specs/gsheets.py +++ b/superset/db_engine_specs/gsheets.py @@ -55,6 +55,11 @@ class GSheetsParametersSchema(Schema): class GSheetsParametersType(TypedDict): service_account_info: str + catalog: Optional[Dict[str, str]] + + +class GSheetsPropertiesType(TypedDict): + parameters: GSheetsParametersType catalog: Dict[str, str] @@ -208,9 +213,18 @@ class GSheetsEngineSpec(SqliteEngineSpec): @classmethod def validate_parameters( cls, - parameters: GSheetsParametersType, + properties: GSheetsParametersType, ) -> List[SupersetError]: errors: List[SupersetError] = [] + + # backwards compatible just incase people are send data + # via parameters for validation + parameters = properties.get("parameters", {}) + if parameters and parameters.get("catalog"): + table_catalog = parameters.get("catalog", {}) + else: + table_catalog = properties.get("catalog", {}) + encrypted_credentials = parameters.get("service_account_info") or "{}" # On create the encrypted credentials are a string, @@ -218,8 +232,6 @@ class GSheetsEngineSpec(SqliteEngineSpec): if isinstance(encrypted_credentials, str): encrypted_credentials = json.loads(encrypted_credentials) - table_catalog = parameters.get("catalog", {}) - if not table_catalog: # Allowing users to submit empty catalogs errors.append( @@ -245,6 +257,7 @@ class GSheetsEngineSpec(SqliteEngineSpec): ) conn = engine.connect() idx = 0 + for name, url in table_catalog.items(): if not name: diff --git a/tests/unit_tests/db_engine_specs/test_gsheets.py b/tests/unit_tests/db_engine_specs/test_gsheets.py index a226653ed5..4a0092b4f7 100644 --- a/tests/unit_tests/db_engine_specs/test_gsheets.py +++ b/tests/unit_tests/db_engine_specs/test_gsheets.py @@ -33,11 +33,38 @@ class ProgrammingError(Exception): def test_validate_parameters_simple() -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, - GSheetsParametersType, + GSheetsPropertiesType, ) - parameters: GSheetsParametersType = { - "service_account_info": "", + properties: GSheetsPropertiesType = { + "parameters": { + "service_account_info": "", + "catalog": {}, + }, + "catalog": {}, + } + errors = GSheetsEngineSpec.validate_parameters(properties) + assert errors == [ + SupersetError( + message="Sheet name is required", + error_type=SupersetErrorType.CONNECTION_MISSING_PARAMETERS_ERROR, + level=ErrorLevel.WARNING, + extra={"catalog": {"idx": 0, "name": True}}, + ), + ] + + +def test_validate_parameters_simple_with_in_root_catalog() -> None: + from superset.db_engine_specs.gsheets import ( + GSheetsEngineSpec, + GSheetsPropertiesType, + ) + + properties: GSheetsPropertiesType = { + "parameters": { + "service_account_info": "", + "catalog": {}, + }, "catalog": {}, } errors = GSheetsEngineSpec.validate_parameters(parameters) @@ -56,7 +83,7 @@ def test_validate_parameters_catalog( ) -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, - GSheetsParametersType, + GSheetsPropertiesType, ) g = mocker.patch("superset.db_engine_specs.gsheets.g") @@ -71,8 +98,8 @@ def test_validate_parameters_catalog( ProgrammingError("Unsupported table: https://www.google.com/"), ] - parameters: GSheetsParametersType = { - "service_account_info": "", + properties: GSheetsPropertiesType = { + "parameters": {"service_account_info": "", "catalog": None}, "catalog": { "private_sheet": "https://docs.google.com/spreadsheets/d/1/edit", "public_sheet": "https://docs.google.com/spreadsheets/d/1/edit#gid=1", @@ -146,7 +173,7 @@ def test_validate_parameters_catalog_and_credentials( ) -> None: from superset.db_engine_specs.gsheets import ( GSheetsEngineSpec, - GSheetsParametersType, + GSheetsPropertiesType, ) g = mocker.patch("superset.db_engine_specs.gsheets.g") @@ -161,8 +188,11 @@ def test_validate_parameters_catalog_and_credentials( ProgrammingError("Unsupported table: https://www.google.com/"), ] - parameters: GSheetsParametersType = { - "service_account_info": "", + properties: GSheetsPropertiesType = { + "parameters": { + "service_account_info": "", + "catalog": None, + }, "catalog": { "private_sheet": "https://docs.google.com/spreadsheets/d/1/edit", "public_sheet": "https://docs.google.com/spreadsheets/d/1/edit#gid=1",
