pinokiod 8.2.6 → 8.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/shell.js +7 -3
- package/package.json +1 -1
- package/test/shell-run-template.test.js +51 -9
package/kernel/shell.js
CHANGED
|
@@ -21,7 +21,7 @@ const ShellParser = require('./shell_parser')
|
|
|
21
21
|
const AnsiStreamTracker = require('./ansi_stream_tracker')
|
|
22
22
|
const ShellStateSync = require('./shell_state_sync')
|
|
23
23
|
const ShellRunTemplate = require('./api/shell_run_template')
|
|
24
|
-
const { PYTHON_INSTALL_SPEC } = require('./bin/conda-pins')
|
|
24
|
+
const { PYTHON_INSTALL_SPEC, PIP_MIN_VERSION } = require('./bin/conda-pins')
|
|
25
25
|
const CondaRuntimeGuard = require('./shell_conda_runtime_guard')
|
|
26
26
|
const home = os.homedir()
|
|
27
27
|
const WINDOWS_CMD_CONDA_COMMAND_PATTERN = /(?:^|[&|()]\s*)@?\s*(?:call\s+)?(?:"[^"]*[\\/]conda(?:\.bat|\.exe)?"|(?:[a-z]:)?[^&|()\s"]*[\\/]conda(?:\.bat|\.exe)?|conda(?:\.bat|\.exe)?)\s+/i
|
|
@@ -1391,9 +1391,9 @@ class Shell {
|
|
|
1391
1391
|
// timeout,
|
|
1392
1392
|
]
|
|
1393
1393
|
} else {
|
|
1394
|
-
// when python version is not specified,
|
|
1394
|
+
// when python version is not specified, use the default python -m venv
|
|
1395
1395
|
venv_activation = [
|
|
1396
|
-
`
|
|
1396
|
+
`python -m venv ${shellEnvPath}`,
|
|
1397
1397
|
activate_command,
|
|
1398
1398
|
// `python -m pip install --upgrade pip setuptools wheel`,
|
|
1399
1399
|
deactivate_path,
|
|
@@ -1403,6 +1403,10 @@ class Shell {
|
|
|
1403
1403
|
]
|
|
1404
1404
|
}
|
|
1405
1405
|
}
|
|
1406
|
+
if (!use_uv) {
|
|
1407
|
+
const updatePip = `uv pip install --exclude-newer-package pip=false "pip>=${PIP_MIN_VERSION}"`
|
|
1408
|
+
venv_activation.push(this.isPowerShell() ? `${updatePip}; if ($LASTEXITCODE -ne 0) { exit 1 }` : `${updatePip} || exit 1`)
|
|
1409
|
+
}
|
|
1406
1410
|
} else {
|
|
1407
1411
|
venv_activation = []
|
|
1408
1412
|
}
|
package/package.json
CHANGED
|
@@ -3,9 +3,11 @@ const fs = require('node:fs/promises')
|
|
|
3
3
|
const os = require('node:os')
|
|
4
4
|
const path = require('node:path')
|
|
5
5
|
const test = require('node:test')
|
|
6
|
+
const { spawnSync } = require('node:child_process')
|
|
6
7
|
|
|
7
8
|
const ShellRunTemplate = require('../kernel/api/shell_run_template')
|
|
8
9
|
const Shell = require('../kernel/shell')
|
|
10
|
+
const { PIP_MIN_VERSION } = require('../kernel/bin/conda-pins')
|
|
9
11
|
|
|
10
12
|
function createKernel(root = process.cwd()) {
|
|
11
13
|
return {
|
|
@@ -379,14 +381,17 @@ test('redactEnvArgs summarizes protected argv env values', () => {
|
|
|
379
381
|
})
|
|
380
382
|
|
|
381
383
|
|
|
382
|
-
test('
|
|
384
|
+
test('venvs preserve creation behavior and enforce the pip minimum across shells', async t => {
|
|
383
385
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-venv-selection-'))
|
|
384
386
|
t.after(() => fs.rm(root, { recursive: true, force: true }))
|
|
385
387
|
const cases = [
|
|
386
|
-
{ venv: 'default-env'
|
|
388
|
+
{ venv: 'default-env' },
|
|
389
|
+
{ venv: { path: 'object-default-env' } },
|
|
387
390
|
{ venv: 'explicit-env', venv_python: '3.10', version: '3.10' },
|
|
388
391
|
{ venv: { path: 'object-env', python: '3.11' }, version: '3.11' },
|
|
389
392
|
{ venv: 'existing-env', existing: true },
|
|
393
|
+
{ venv: 'existing-env', venv_python: '3.10', version: '3.10', existing: true },
|
|
394
|
+
{},
|
|
390
395
|
]
|
|
391
396
|
await fs.mkdir(path.join(root, 'existing-env'))
|
|
392
397
|
for (const [platform, shellName] of [
|
|
@@ -408,17 +413,54 @@ test('venv creation preserves interpreter selection and existing environments ac
|
|
|
408
413
|
message: 'echo PINOKIO_REQUIREMENTS_RAN',
|
|
409
414
|
})
|
|
410
415
|
const command = shell.build(params)
|
|
411
|
-
assert.doesNotMatch(command,
|
|
416
|
+
assert.doesNotMatch(command, /--seed|--no-config|--python-preference|python -I|files\.pythonhosted\.org/)
|
|
412
417
|
assert.match(command, /echo PINOKIO_REQUIREMENTS_RAN$/)
|
|
413
|
-
if (scenario.existing) {
|
|
414
|
-
assert.doesNotMatch(command, /uv venv
|
|
415
|
-
} else if (scenario.
|
|
416
|
-
assert.match(command, /uv venv --seed --python-preference only-system --python python /)
|
|
417
|
-
} else {
|
|
418
|
+
if (!scenario.venv || scenario.existing) {
|
|
419
|
+
assert.doesNotMatch(command, /python -m venv|uv venv/)
|
|
420
|
+
} else if (scenario.version) {
|
|
418
421
|
assert.ok(command.includes(` --python ${scenario.version}`), command)
|
|
419
|
-
assert.doesNotMatch(command,
|
|
422
|
+
assert.doesNotMatch(command, /python -m venv/)
|
|
423
|
+
} else {
|
|
424
|
+
assert.match(command, /python -m venv /)
|
|
425
|
+
}
|
|
426
|
+
const updatePip = `uv pip install --exclude-newer-package pip=false "pip>=${PIP_MIN_VERSION}"`
|
|
427
|
+
if (scenario.venv && !scenario.version) {
|
|
428
|
+
assert.equal(command.split(updatePip).length - 1, 1)
|
|
429
|
+
assert.ok(command.indexOf(updatePip) > command.lastIndexOf('activate'))
|
|
430
|
+
assert.ok(command.includes(shell.isPowerShell()
|
|
431
|
+
? `${updatePip}; if ($LASTEXITCODE -ne 0) { exit 1 }`
|
|
432
|
+
: `${updatePip} || exit 1`))
|
|
433
|
+
} else {
|
|
434
|
+
assert.doesNotMatch(command, /uv pip install/)
|
|
420
435
|
}
|
|
421
436
|
assert.equal(shell.env.UV_PYTHON_PREFERENCE, 'only-managed')
|
|
422
437
|
}
|
|
423
438
|
}
|
|
424
439
|
})
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
test('failed pip updates stop the application even with an unconditional command chain', async t => {
|
|
443
|
+
if (process.platform === 'win32') return t.skip('executes the POSIX shell failure guard')
|
|
444
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-pip-failure-'))
|
|
445
|
+
t.after(() => fs.rm(root, { recursive: true, force: true }))
|
|
446
|
+
const binDir = path.join(root, 'bin')
|
|
447
|
+
await fs.mkdir(path.join(root, 'env', 'bin'), { recursive: true })
|
|
448
|
+
await fs.mkdir(binDir)
|
|
449
|
+
await fs.writeFile(path.join(root, 'env', 'bin', 'activate'), 'true\n')
|
|
450
|
+
await fs.writeFile(path.join(binDir, 'uv'), '#!/bin/sh\nexit "$PINOKIO_TEST_UV_EXIT_CODE"\n', { mode: 0o755 })
|
|
451
|
+
const shell = createShell(createKernel(root))
|
|
452
|
+
shell.shell = 'bash'
|
|
453
|
+
const params = await shell.activate({
|
|
454
|
+
path: root, conda: { skip: true }, venv: 'env',
|
|
455
|
+
chain: '*', message: 'echo PINOKIO_APPLICATION_RAN',
|
|
456
|
+
})
|
|
457
|
+
const command = shell.build(params)
|
|
458
|
+
for (const exitCode of [0, 7]) {
|
|
459
|
+
const result = spawnSync('/bin/bash', ['-c', command], {
|
|
460
|
+
encoding: 'utf8',
|
|
461
|
+
env: { ...process.env, PATH: `${binDir}${path.delimiter}${process.env.PATH}`, PINOKIO_TEST_UV_EXIT_CODE: String(exitCode) },
|
|
462
|
+
})
|
|
463
|
+
assert.equal(result.status, exitCode ? 1 : 0, result.stderr)
|
|
464
|
+
assert.equal(result.stdout.includes('PINOKIO_APPLICATION_RAN'), exitCode === 0)
|
|
465
|
+
}
|
|
466
|
+
})
|