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 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, seed pip using the activated Python
1394
+ // when python version is not specified, use the default python -m venv
1395
1395
  venv_activation = [
1396
- `uv venv --seed --python-preference only-system --python python ${shellEnvPath}`,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "8.2.6",
3
+ "version": "8.2.7",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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('venv creation preserves interpreter selection and existing environments across shells', async t => {
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', seeded: true },
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, /python -m venv|python -I|files\.pythonhosted\.org|\|\| exit 1/)
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|--seed/)
415
- } else if (scenario.seeded) {
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, /--seed|--python-preference only-system/)
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
+ })