Skip to content

Commit 4eb62b2

Browse files
committed
refactor(python): use downloadBinary from socket-lib for Python downloads
Simplifies Python tarball download by using the new downloadBinary helper from @socketsecurity/lib 2.8.4 instead of dlxBinary with workarounds. - Replaces dlxBinary (which attempts execution) with downloadBinary - Removes workaround for catching execution errors on tarball - Cleaner separation: downloadBinary for download, tar for extraction
1 parent 398c0d2 commit 4eb62b2

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

packages/cli/src/utils/python/standalone.mts

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,11 @@ import semver from 'semver'
4848

4949
import { whichBin } from '@socketsecurity/lib/bin'
5050
import { WIN32 } from '@socketsecurity/lib/constants/platform'
51-
import { httpDownload } from '@socketsecurity/lib/http-request'
51+
import { downloadBinary, getDlxCachePath } from '@socketsecurity/lib/dlx-binary'
5252
import { spawn } from '@socketsecurity/lib/spawn'
5353

5454
import ENV from '../../constants/env.mts'
5555
import { PYTHON_MIN_VERSION } from '../../constants/packages.mts'
56-
import { getDlxCachePath } from '../dlx/binary.mts'
5756
import { resolvePyCli } from '../dlx/resolve-binary.mjs'
5857
import { getErrorCause, InputError } from '../error/errors.mts'
5958

@@ -186,31 +185,32 @@ export async function checkSystemPython(): Promise<string | null> {
186185
}
187186

188187
/**
189-
* Download and extract Python from python-build-standalone.
188+
* Download and extract Python from python-build-standalone using downloadBinary.
189+
* Uses downloadBinary for caching, checksum verification, and download management.
190190
*/
191191
async function downloadPython(pythonDir: string): Promise<void> {
192192
const url = getPythonStandaloneUrl()
193-
const tarballPath = path.join(pythonDir, 'python.tar.gz')
193+
const tarballName = 'python-standalone.tar.gz'
194194

195-
// Ensure directory exists
195+
// Ensure directory exists.
196196
await fs.mkdir(pythonDir, { recursive: true })
197197

198-
// Download with Node's native http module
199198
try {
200-
await httpDownload(url, tarballPath)
199+
// Use downloadBinary to download the tarball with caching (without execution).
200+
const result = await downloadBinary({
201+
url,
202+
name: tarballName,
203+
})
204+
205+
// Extract the tarball to pythonDir.
206+
await spawn('tar', ['-xzf', result.binaryPath, '-C', pythonDir], {
207+
shell: WIN32,
208+
})
201209
} catch (error) {
202210
throw new InputError(
203211
`Failed to download Python: ${error instanceof Error ? error.message : String(error)}`,
204212
)
205213
}
206-
207-
// Extract using system tar command
208-
await spawn('tar', ['-xzf', tarballPath, '-C', pythonDir], {
209-
shell: WIN32,
210-
})
211-
212-
// Clean up tarball.
213-
await fs.rm(tarballPath, { force: true })
214214
}
215215

216216
/**
@@ -260,6 +260,26 @@ async function isSocketCliInstalled(pythonBin: string): Promise<boolean> {
260260
}
261261
}
262262

263+
/**
264+
* Convert npm caret range (^2.2.15) to pip version specifier (>=2.2.15,<3.0.0).
265+
*/
266+
function convertCaretToPipRange(caretRange: string): string {
267+
if (!caretRange) {
268+
return ''
269+
}
270+
271+
if (!caretRange.startsWith('^')) {
272+
return `==${caretRange}`
273+
}
274+
275+
const version = caretRange.slice(1) // Remove '^'
276+
const parts = version.split('.')
277+
const major = Number.parseInt(parts[0] || '0', 10)
278+
const nextMajor = major + 1
279+
280+
return `>=${version},<${nextMajor}.0.0`
281+
}
282+
263283
/**
264284
* Install socketsecurity package into the Python environment.
265285
*/
@@ -269,10 +289,15 @@ export async function ensureSocketCli(pythonBin: string): Promise<void> {
269289
return
270290
}
271291

272-
// Install socketsecurity
292+
// Get version constraint from inlined environment variable.
293+
const pyCliVersion = ENV.INLINED_SOCKET_CLI_PYCLI_VERSION
294+
const versionSpec = convertCaretToPipRange(pyCliVersion || '')
295+
const packageSpec = versionSpec ? `socketsecurity${versionSpec}` : 'socketsecurity'
296+
297+
// Install socketsecurity with version constraint.
273298
await spawn(
274299
pythonBin,
275-
['-m', 'pip', 'install', '--quiet', 'socketsecurity'],
300+
['-m', 'pip', 'install', '--quiet', packageSpec],
276301
{
277302
shell: WIN32,
278303
stdio: 'inherit',

0 commit comments

Comments
 (0)