Skip to content

fix: preserve fish activation environment - #431

Open
jihtsan wants to merge 2 commits into
ekalinin:masterfrom
jihtsan:codex/399-fish-preserve-environment
Open

jihtsan wants to merge 2 commits into
ekalinin:masterfrom
jihtsan:codex/399-fish-preserve-environment

Conversation

@jihtsan

@jihtsan jihtsan commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Fish activation currently erases the caller's NODE_PATH, NPM_CONFIG_PREFIX and npm_config_prefix before saving them. Save their original values and restore them only when leaving an active nodeenv, preserving the distinction between an empty value and an unset variable.

While active, replace NODE_PATH with the environment's module directory, matching the other shells' isolation behavior. Put the --isolate-npm restoration under the same active-environment guard, preserve empty cache/userconfig/init-module values, and remove the saved variables after restoring them. Repeated activation and nondestructive deactivation retain the original environment.

Behavioral tests now check the entire active NODE_PATH, all six restored variables, backup cleanup, unset/empty values, multiple paths, spaces and repeated operations, with and without --isolate-npm. The shell-requirement comment is current, and CHANGES notes that existing environments need --force to regenerate activate.fish.

Validation on macOS with fish 4.9.3:

  • Strengthened regression tests against prior head 22e3d4b: 5 failed, 29 passed. All pass with this correction.
  • NODEENV_REQUIRE_SHELLS=1 python -m pytest tests/test_activate_shells.py: 114 passed on each of Python 3.10.21 and 3.13.12, running sh, dash, bash, zsh and fish.
  • python -m pytest -m 'not integration' tests: 411 passed / 1 failed / 11 skipped on Python 3.10; 412 passed / 1 failed / 10 skipped on Python 3.13; 5 integration cases deselected in each.
  • The one failure is test_mirror_credentials_stay_out_of_error_messages, which receives HTTP 503 in this local environment. It fails with the same HTTP 503 on unchanged prior head 22e3d4b under both Python versions. With only that confirmed baseline case additionally excluded, the remaining 411 / 412 tests pass.
  • flake8 --extend-ignore=E127 nodeenv.py tests setup.py and git diff --check: passed.

Older fish releases, other Python versions, Linux/Windows execution and real Node download/build integration are not covered by these local checks. Upstream CI results must be checked against the new head.

Closes #399.

@ekalinin
ekalinin self-requested a review October 16, 2026 16:22

@ekalinin ekalinin left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this fixes #399. Two changes are needed before merge, plus two small ones.

  • [P1] Keep fish replacing NODE_PATH - nodeenv.py:2227

    This prepend branch has never run since fish support landed in 2017: the initial deactivate_node nondestructive pass erased NODE_PATH first, so fish replaced it like the other shells. Now it runs, and modules from the user's NODE_PATH resolve inside the env, under fish only. Please replace it, as the prefix variables below do:

    if set -q NODE_PATH
        set -gx _OLD_NODE_PATH $NODE_PATH
    end
    set -gx NODE_PATH "$NODE_VIRTUAL_ENV/__MOD_NAME__"

    Then test_activate_sets_env (tests/test_activate_shells.py:283) can compare the whole NODE_PATH, not just its first element.

  • [P2] Same fix for the --isolate-npm restore - nodeenv.py:1768

    It still uses test -n, so an empty npm_config_* becomes unset and leaves an exported empty _OLD_npm_config_* behind. Please move __NPM_UNISOLATE__ inside the new guard, drop its duplicate guard, switch to set -q, and add the three npm_config_* names to names in test_fish_restores_original_variables.

  • [P3] The REQUIRE_SHELLS comment (tests/test_activate_shells.py:144) still refers to xfail markers, which this PR removes.

  • [P3] Please add an [unreleased] entry for #399 to CHANGES, noting that existing envs need --force to get the new activate.fish.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

activate.fish erases a pre-existing NODE_PATH and never restores it

2 participants