11import path from 'path'
22import { Page } from '@playwright/test'
3- import { exec } from 'child_process'
4- import { promisify } from 'util'
3+ import { execAsync } from '../src/utilities/exec'
54
65// Where your extension lives on disk
76export const EXT_PATH = path . resolve ( __dirname , '..' )
@@ -34,25 +33,36 @@ export const clickExplorerTab = async (page: Page): Promise<void> => {
3433 }
3534}
3635
37- const execAsync = promisify ( exec )
38-
3936export interface PythonEnvironment {
4037 pythonPath : string
4138 pipPath : string
4239}
4340
4441/**
45- * Create a virtual environment in the given directory.
42+ * Create a virtual environment in the given directory using uv .
4643 * @param venvDir The directory to create the virtual environment in.
4744 */
4845export const createVirtualEnvironment = async (
4946 venvDir : string ,
5047) : Promise < PythonEnvironment > => {
51- const pythonCmd = process . platform === 'win32' ? 'python' : 'python3'
52- const { stderr } = await execAsync ( `${ pythonCmd } -m venv "${ venvDir } "` )
53- if ( stderr && ! stderr . includes ( 'WARNING' ) ) {
54- throw new Error ( `Failed to create venv: ${ stderr } ` )
48+ // Try to use uv first, fallback to python -m venv
49+ try {
50+ const { exitCode, stderr } = await execAsync ( `uv venv "${ venvDir } "` )
51+ if ( exitCode !== 0 ) {
52+ throw new Error ( `Failed to create venv with uv: ${ stderr } ` )
53+ }
54+ } catch ( error ) {
55+ // Fallback to python -m venv if uv is not available
56+ console . warn ( 'uv not available, falling back to python -m venv' )
57+ const pythonCmd = process . platform === 'win32' ? 'python' : 'python3'
58+ const { stderr, exitCode } = await execAsync (
59+ `${ pythonCmd } -m venv "${ venvDir } "` ,
60+ )
61+ if ( exitCode !== 0 ) {
62+ throw new Error ( `Failed to create venv: ${ stderr } ` )
63+ }
5564 }
65+
5666 // Get paths
5767 const isWindows = process . platform === 'win32'
5868 const binDir = path . join ( venvDir , isWindows ? 'Scripts' : 'bin' )
@@ -66,19 +76,33 @@ export const createVirtualEnvironment = async (
6676}
6777
6878/**
69- * Install packages in the given virtual environment.
79+ * Install packages in the given virtual environment using uv (with pip fallback) .
7080 * @param pythonDetails The Python environment to use.
7181 * @param packagePaths The paths to the packages to install (string[]).
7282 */
7383export const pipInstall = async (
7484 pythonDetails : PythonEnvironment ,
7585 packagePaths : string [ ] ,
7686) : Promise < void > => {
77- const { pipPath } = pythonDetails
78- const execString = `"${ pipPath } " install -e "${ packagePaths . join ( '" -e "' ) } "`
79- const { stderr } = await execAsync ( execString )
80- if ( stderr && ! stderr . includes ( 'WARNING' ) && ! stderr . includes ( 'notice' ) ) {
81- throw new Error ( `Failed to install package: ${ stderr } ` )
87+ // Try to use uv first, fallback to pip
88+ try {
89+ const packages = packagePaths . map ( pkg => `-e "${ pkg } "` ) . join ( ' ' )
90+ const execString = `uv pip install --python "${ pythonDetails . pythonPath } " ${ packages } `
91+ const { stderr, exitCode } = await execAsync ( execString )
92+ if ( exitCode !== 0 ) {
93+ throw new Error ( `Failed to install package with uv: ${ stderr } ` )
94+ }
95+ } catch ( error ) {
96+ // Fallback to pip if uv is not available
97+ console . warn (
98+ `uv not available, falling back to pip, because of the error ${ error } ` ,
99+ )
100+ const { pipPath } = pythonDetails
101+ const execString = `"${ pipPath } " install -e "${ packagePaths . join ( '" -e "' ) } "`
102+ const { stderr, exitCode } = await execAsync ( execString )
103+ if ( exitCode !== 0 ) {
104+ throw new Error ( `Failed to install package: ${ stderr } ` )
105+ }
82106 }
83107}
84108
0 commit comments