From 0770a179ee4973e6a01769cc11cb57279060571b Mon Sep 17 00:00:00 2001 From: Ben King <9087625+benfdking@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:15:41 +0100 Subject: [PATCH 1/2] feat(vscode): handling python errors well --- sqlmesh/core/config/loader.py | 10 ++++- vscode/extension/tests/broken_project.spec.ts | 41 ++++++++++++++++++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/sqlmesh/core/config/loader.py b/sqlmesh/core/config/loader.py index 7f1789a677..bee0e19a4f 100644 --- a/sqlmesh/core/config/loader.py +++ b/sqlmesh/core/config/loader.py @@ -184,8 +184,14 @@ def load_config_from_python_module( module_path: Path, config_name: str = "config", ) -> C: - with sys_path(module_path.parent): - config_module = import_python_file(module_path, module_path.parent) + try: + with sys_path(module_path.parent): + config_module = import_python_file(module_path, module_path.parent) + except Exception as e: + raise ConfigError( + f"Failed to load config file: {str(e)}", + location=module_path, + ) try: config_obj = getattr(config_module, config_name) diff --git a/vscode/extension/tests/broken_project.spec.ts b/vscode/extension/tests/broken_project.spec.ts index f2af3e13e0..c6be73e403 100644 --- a/vscode/extension/tests/broken_project.spec.ts +++ b/vscode/extension/tests/broken_project.spec.ts @@ -395,9 +395,46 @@ test.describe('Bad config.py/config.yaml file issues', () => { await runCommand(page, 'View: Focus Problems') // Assert that the error is present in the problems view - await page + const errorElement = page .getByText('Config needs to be a valid object of type') .first() - .isVisible({ timeout: 5_000 }) + await expect(errorElement).toBeVisible({ timeout: 5000 }) + }) + + test('sushi example, bad config.py', async ({ page, sharedCodeServer }) => { + const tempDir = await fs.mkdtemp( + path.join(os.tmpdir(), 'vscode-test-tcloud-'), + ) + await fs.copy(SUSHI_SOURCE_PATH, tempDir) + await createPythonInterpreterSettingsSpecifier(tempDir) + + const configPyPath = path.join(tempDir, 'config.py') + // Write an invalid Python to config.py + await fs.writeFile(configPyPath, 'invalid_python_code = [1, 2, 3') + + await page.goto( + `http://127.0.1:${sharedCodeServer.codeServerPort}/?folder=${tempDir}`, + ) + await page.waitForLoadState('networkidle') + + // Open customers.sql model + await page + .getByRole('treeitem', { name: 'models', exact: true }) + .locator('a') + .click() + await page + .getByRole('treeitem', { name: 'customers.sql', exact: true }) + .locator('a') + .click() + + // Expect the error to appear + await page.waitForSelector('text=Error creating context') + + // Open the problems view + await runCommand(page, 'View: Focus Problems') + + // Assert that the error is present in the problems view + const errorElement = page.getByText('Failed to load config file:').first() + await expect(errorElement).toBeVisible({ timeout: 5000 }) }) }) From 532084e934d80d2c57c19ce8db4e74b58537bbff Mon Sep 17 00:00:00 2001 From: Ben <9087625+benfdking@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:40:59 +0100 Subject: [PATCH 2/2] Update sqlmesh/core/config/loader.py Co-authored-by: Themis Valtinos <73662635+themisvaltinos@users.noreply.github.com> --- sqlmesh/core/config/loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlmesh/core/config/loader.py b/sqlmesh/core/config/loader.py index bee0e19a4f..c381252fb9 100644 --- a/sqlmesh/core/config/loader.py +++ b/sqlmesh/core/config/loader.py @@ -189,7 +189,7 @@ def load_config_from_python_module( config_module = import_python_file(module_path, module_path.parent) except Exception as e: raise ConfigError( - f"Failed to load config file: {str(e)}", + f"Failed to load config file: {e}", location=module_path, )