Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions vscode/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
"title": "SQLMesh: Restart Servers",
"description": "SQLMesh"
},
{
"command": "sqlmesh.printEnvironment",
"title": "SQLMesh: Print Environment Variables",
"description": "SQLMesh"
},
{
"command": "sqlmesh.signin",
"title": "SQLMesh: Sign in to Tobiko Cloud",
Expand Down
40 changes: 40 additions & 0 deletions vscode/extension/src/commands/printEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as vscode from 'vscode'
import { getSqlmeshEnvironment } from '../utilities/sqlmesh/sqlmesh'
import { isErr } from '@bus/result'
import { IS_WINDOWS } from '../utilities/isWindows'

export function printEnvironment() {
return async () => {
const envResult = await getSqlmeshEnvironment()

if (isErr(envResult)) {
await vscode.window.showErrorMessage(envResult.error)
return
}

const env = envResult.value

// Create a new terminal with the SQLMesh environment
const terminal = vscode.window.createTerminal({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe possible future improvement instead of always creating a new terminal to see if one exists already

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My hesitation is that the whole point of this is to show what the lsp runs in. If you reuse, you don't quite get that.

name: 'SQLMesh Environment',
env: env,
})

// Show the terminal
terminal.show()

// Run the appropriate command to display environment variables
if (IS_WINDOWS) {
// On Windows, use 'set' command
terminal.sendText('set')
} else {
// On Unix-like systems, use 'env' command
terminal.sendText('env | sort')
}

// Show a notification
vscode.window.showInformationMessage(
'SQLMesh environment variables displayed in terminal',
)
}
}
2 changes: 2 additions & 0 deletions vscode/extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { signIn } from './commands/signin'
import { signInSpecifyFlow } from './commands/signinSpecifyFlow'
import { renderModel, reRenderModelForSourceFile } from './commands/renderModel'
import { stop } from './commands/stop'
import { printEnvironment } from './commands/printEnvironment'
import { isErr } from '@bus/result'
import { handleError } from './utilities/errors'
import { selector, completionProvider } from './completion/completion'
Expand Down Expand Up @@ -161,6 +162,7 @@ export async function activate(context: vscode.ExtensionContext) {
await restart()
}),
registerCommand(`sqlmesh.stop`, stop(lspClient)),
registerCommand(`sqlmesh.printEnvironment`, printEnvironment()),
)

const result = await lspClient.start()
Expand Down
18 changes: 2 additions & 16 deletions vscode/extension/src/lsp/lsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,7 @@ export class LSPClient implements Disposable {
transport: TransportKind.stdio,
options: {
cwd: workspacePath,
// TODO: This is a temporary fix to avoid the issue with the LSP server
// crashing when the number of workers is too high. This is a workaround
// to avoid the issue. Once fixed, we should remove the whole env block.
env: {
MAX_FORK_WORKERS: '1',
...process.env,
...sqlmesh.value.env,
},
env: sqlmesh.value.env,
},
args: sqlmesh.value.args,
},
Expand All @@ -97,14 +90,7 @@ export class LSPClient implements Disposable {
transport: TransportKind.stdio,
options: {
cwd: workspacePath,
env: {
// TODO: This is a temporary fix to avoid the issue with the LSP server
// crashing when the number of workers is too high. This is a workaround
// to avoid the issue. Once fixed, we should remove the whole env block.
MAX_FORK_WORKERS: '1',
...process.env,
...sqlmesh.value.env,
},
env: sqlmesh.value.env,
},
args: sqlmesh.value.args,
},
Expand Down
103 changes: 71 additions & 32 deletions vscode/extension/src/utilities/sqlmesh/sqlmesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,41 @@ export interface SqlmeshExecInfo {
args: string[]
}

/**
* Gets the current SQLMesh environment variables that would be used for execution.
* This is useful for debugging and understanding the environment configuration.
*
* @returns A Result containing the environment variables or an error
*/
export async function getSqlmeshEnvironment(): Promise<Result<Record<string, string>, string>> {
const interpreterDetails = await getInterpreterDetails()
const envVariables = await getPythonEnvVariables()
if (isErr(envVariables)) {
return err(envVariables.error)
}

const binPath = interpreterDetails.binPath
const virtualEnvPath = binPath && interpreterDetails.isVirtualEnvironment
? path.dirname(path.dirname(binPath)) // binPath points to bin dir in venv
: binPath ? path.dirname(binPath) : undefined

const env: Record<string, string> = {
...process.env,
...envVariables.value,
PYTHONPATH: interpreterDetails.path?.[0] ?? '',
}

if (virtualEnvPath) {
env['VIRTUAL_ENV'] = virtualEnvPath
}

if (binPath) {
env['PATH'] = `${binPath}${path.delimiter}${process.env.PATH || ''}`
}

return ok(env)
}

/**
* Returns true if the current project is a Tcloud project. To detect this we,
* 1. Check if the project has a tcloud.yaml file in the project root. If it does, we assume it's a Tcloud project.
Expand Down Expand Up @@ -68,23 +103,17 @@ export const getTcloudBin = async (): Promise<Result<SqlmeshExecInfo, ErrorType>
if (!fs.existsSync(binPath)) {
return err({type: 'tcloud_bin_not_found'})
}
const envVariables = await getPythonEnvVariables()
if (isErr(envVariables)) {
const env = await getSqlmeshEnvironment()
if (isErr(env)) {
return err({
type: 'generic',
message: envVariables.error,
message: env.error,
})
}
return ok({
bin: binPath,
workspacePath: interpreterDetails.resource?.fsPath ?? '',
env: {
...process.env,
...envVariables.value,
PYTHONPATH: interpreterDetails.path[0],
VIRTUAL_ENV: path.dirname(interpreterDetails.binPath!),
PATH: `${interpreterDetails.binPath!}${path.delimiter}${process.env.PATH || ''}`,
},
env: env.value,
args: [],
})
}
Expand Down Expand Up @@ -300,16 +329,17 @@ export const sqlmeshExec = async (): Promise<
}
const binPath = path.join(interpreterDetails.binPath!, sqlmesh)
traceLog(`Bin path: ${binPath}`)
const env = await getSqlmeshEnvironment()
if (isErr(env)) {
return err({
type: 'generic',
message: env.error,
})
}
return ok({
bin: binPath,
workspacePath,
env: {
...process.env,
...envVariables.value,
PYTHONPATH: interpreterDetails.path?.[0],
VIRTUAL_ENV: path.dirname(path.dirname(interpreterDetails.binPath!)), // binPath now points to bin dir
PATH: `${interpreterDetails.binPath!}${path.delimiter}${process.env.PATH || ''}`,
},
env: env.value,
args: [],
})
} else {
Expand All @@ -319,13 +349,17 @@ export const sqlmeshExec = async (): Promise<
type: 'sqlmesh_not_found',
})
}
const env = await getSqlmeshEnvironment()
if (isErr(env)) {
return err({
type: 'generic',
message: env.error,
})
}
return ok({
bin: sqlmesh,
workspacePath,
env: {
...process.env,
...envVariables.value,
},
env: env.value,
args: [],
})
}
Expand Down Expand Up @@ -455,19 +489,27 @@ export const sqlmeshLspExec = async (): Promise<
if (isErr(ensuredDependencies)) {
return ensuredDependencies
}
const env = await getSqlmeshEnvironment()
if (isErr(env)) {
return err({
type: 'generic',
message: env.error,
})
}
return ok({
bin: binPath,
workspacePath,
env: {
...process.env,
...envVariables.value,
PYTHONPATH: interpreterDetails.path?.[0],
VIRTUAL_ENV: path.dirname(path.dirname(interpreterDetails.binPath!)), // binPath now points to bin dir
PATH: `${interpreterDetails.binPath!}${path.delimiter}${process.env.PATH || ''}`, // binPath already points to the bin directory
},
env: env.value,
args: [],
})
} else {
const env = await getSqlmeshEnvironment()
if (isErr(env)) {
return err({
type: 'generic',
message: env.error,
})
}
const exists = await doesExecutableExist(sqlmeshLSP)
if (!exists) {
return err({
Expand All @@ -477,10 +519,7 @@ export const sqlmeshLspExec = async (): Promise<
return ok({
bin: sqlmeshLSP,
workspacePath,
env: {
...process.env,
...envVariables.value,
},
env: env.value,
args: [],
})
}
Expand Down