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
57 changes: 57 additions & 0 deletions src/common/logging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as util from 'node:util'
import type { Disposable, LogOutputChannel } from 'vscode'

type Arguments = unknown[]
class OutputChannelLogger {
constructor(private readonly channel: LogOutputChannel) {}

public traceLog(...data: Arguments): void {
this.channel.appendLine(util.format(...data))
}

public traceError(...data: Arguments): void {
this.channel.error(util.format(...data))
}

public traceWarn(...data: Arguments): void {
this.channel.warn(util.format(...data))
}

public traceInfo(...data: Arguments): void {
this.channel.info(util.format(...data))
}

public traceVerbose(...data: Arguments): void {
this.channel.debug(util.format(...data))
}
}

let channel: OutputChannelLogger | undefined
export function registerLogger(logChannel: LogOutputChannel): Disposable {
channel = new OutputChannelLogger(logChannel)
return {
dispose: () => {
channel = undefined
},
}
}

export function traceLog(...args: Arguments): void {
channel?.traceLog(...args)
}

export function traceError(...args: Arguments): void {
channel?.traceError(...args)
}

export function traceWarn(...args: Arguments): void {
channel?.traceWarn(...args)
}

export function traceInfo(...args: Arguments): void {
channel?.traceInfo(...args)
}

export function traceVerbose(...args: Arguments): void {
channel?.traceVerbose(...args)
}
5 changes: 3 additions & 2 deletions src/common/scope-map.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import paths from 'node:path'
import { Uri } from 'vscode'
import type { PythonEnvironment } from '../vscode-python-environments'
import { traceLog } from './logging'

export class ScopeMap {
map: Map<string | undefined, PythonEnvironment>
Expand All @@ -23,10 +24,10 @@ export class ScopeMap {
while (key && !this.map.has(key.fsPath)) {
const parent = paths.dirname(key.fsPath)
if (parent === key.fsPath) {
console.log('hit root from', keyOrig?.fsPath)
traceLog('hit root from', keyOrig?.fsPath)
break
}
console.log('no env for %s, trying %s', key.fsPath, parent)
traceLog(`no env for ${key.fsPath}, trying ${parent}`)
key = Uri.file(parent)
}
return this.map.get(key?.fsPath)
Expand Down
6 changes: 4 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { type ExtensionContext, window } from 'vscode'
import { registerLogger } from './common/logging'
import { HatchEnvManager } from './hatch-env-manager'
import { getEnvExtApi } from './python-envs-api'

export async function activate(context: ExtensionContext) {
const log = window.createOutputChannel('Hatch', { log: true })
context.subscriptions.push(log)

context.subscriptions.push(log, registerLogger(log))

const api = await getEnvExtApi()
const envManager = new HatchEnvManager(api, log)
const envManager = new HatchEnvManager(api)
context.subscriptions.push(api.registerEnvironmentManager(envManager))
}

Expand Down
3 changes: 2 additions & 1 deletion src/hatch-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from 'node:child_process'
import { promisify } from 'node:util'
import type { Uri } from 'vscode'
import { traceError } from './common/logging'

const execFile = promisify(execFileCb)

Expand Down Expand Up @@ -71,7 +72,7 @@ async function run(cmd: string, args: string[], opts: ProcessEnvOptions): Promis
return stdout
} catch (e) {
const err = e as ExecFileException
console.error(err, err.stderr)
traceError(err, err.stderr)
throw err
}
}
23 changes: 10 additions & 13 deletions src/hatch-env-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import * as fs from 'fs-extra'
import {
EventEmitter,
type IconPath,
type LogOutputChannel,
type MarkdownString,
ProgressLocation,
Uri,
window,
} from 'vscode'
import { HATCH_ID, HATCH_NAME } from './common/constants'
import { type Deferred, createDeferred } from './common/deferred'
import { traceInfo, traceVerbose } from './common/logging'
import { isWindows } from './common/platform'
import { ScopeMap } from './common/scope-map'
import * as hatch from './hatch-cli'
Expand Down Expand Up @@ -48,10 +48,7 @@ export class HatchEnvManager implements EnvironmentManager {
path2envs: Map<string, Map<string, PythonEnvironment>>
activeEnvs: ScopeMap

constructor(
private readonly api: PythonEnvironmentApi,
readonly log?: LogOutputChannel,
) {
constructor(private readonly api: PythonEnvironmentApi) {
this.path2envs = new Map()
this.activeEnvs = new ScopeMap()
}
Expand Down Expand Up @@ -93,7 +90,7 @@ export class HatchEnvManager implements EnvironmentManager {
} else {
const project = this.api.getPythonProject(scope)
if (project) {
this.log?.info('Refreshing project %s', project.uri.fsPath)
traceInfo('Refreshing project %s', project.uri.fsPath)
await this.fetchEnvsForProjects([project])
}
}
Expand All @@ -105,16 +102,16 @@ export class HatchEnvManager implements EnvironmentManager {
await this.initialize()

if (scope === 'global') {
this.log?.debug("getEnvironments called with scope 'global'")
traceVerbose("getEnvironments called with scope 'global'")
return [] // TODO: maybe create shims for Hatch-downloadable Pythons?
}

if (scope === 'all') {
this.log?.debug("getEnvironments called with scope 'all'")
traceVerbose("getEnvironments called with scope 'all'")
const allEnvs = Array.from(this.path2envs.values()).flatMap((envs) =>
Array.from(envs.values()),
)
this.log?.debug('Found %d environments in cache', allEnvs.length)
traceVerbose('Found %d environments in cache', allEnvs.length)
return allEnvs
}

Expand All @@ -126,7 +123,7 @@ export class HatchEnvManager implements EnvironmentManager {
const cachedEnvs = Array.from(this.path2envs.get(project.uri.fsPath)?.values() ?? [])
const uncached = !this.path2envs.has(project.uri.fsPath)
if (!uncached) {
this.log?.info('Found %d cached envs', cachedEnvs.length)
traceInfo('Found %d cached envs', cachedEnvs.length)
return cachedEnvs
}
await this.fetchEnvsForProjects([project])
Expand All @@ -136,10 +133,10 @@ export class HatchEnvManager implements EnvironmentManager {
async set(scope: SetEnvironmentScope, env?: PythonEnvironment): Promise<void> {
for (const uri of Array.isArray(scope) ? scope : [scope]) {
if (!env) {
this.log?.info('unsetting env for scope %s', uri?.fsPath)
traceInfo('unsetting env for scope %s', uri?.fsPath)
this.activeEnvs.delete(uri)
} else {
this.log?.info('setting env %s for scope %s', env.displayName, uri?.fsPath)
traceInfo('setting env %s for scope %s', env.displayName, uri?.fsPath)
if (uri) {
await hatch.createEnv(env.name, uri, { existOk: true })
}
Expand Down Expand Up @@ -182,7 +179,7 @@ export class HatchEnvManager implements EnvironmentManager {
await hatch.createEnv(env.name, scope, { existOk: true })
}

this.log?.info(`got env ${env?.displayName} for scope ${scope?.fsPath}`)
traceInfo(`got env ${env?.displayName} for scope ${scope?.fsPath}`)
return env
}

Expand Down