Skip to content

Commit e0410ca

Browse files
authored
Nushell activation scripts (pypa#2170)
1 parent 1cc503b commit e0410ca

File tree

7 files changed

+117
-2
lines changed

7 files changed

+117
-2
lines changed

.github/workflows/check.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ jobs:
4040
run: |
4141
for i in 1 2 3; do
4242
echo "try $i" && \
43-
${{ runner.os == 'Linux' && 'sudo apt-get update -y && sudo apt-get install fish csh' || true}} && \
44-
${{ runner.os == 'macOS' && 'brew install fish tcsh' || true}} && \
43+
${{ runner.os == 'Linux' && 'sudo apt-get update -y && sudo apt-get install fish csh -y' || true }} && \
44+
${{ runner.os == 'Linux' && 'sudo apt-get install curl wget -y' || true }} && \
45+
${{ runner.os == 'Linux' && 'nushell_url=$(curl -s https://api.github.com/repos/nushell/nushell/releases/latest | grep "browser_" | cut -d\" -f4 | grep .tar.gz)' || true }} && \
46+
${{ runner.os == 'Linux' && 'wget -O nushell.tar.gz $nushell_url' || true }} && \
47+
${{ runner.os == 'Linux' && 'tar -zxf nushell.tar.gz --one-top-level=nushell --strip-components=2' || true }} && \
48+
${{ runner.os == 'Linux' && 'sudo cp nushell/nu /usr/bin' || true }} && \
49+
${{ runner.os == 'Windows' && 'choco install nushell' || true }} && \
50+
${{ runner.os == 'macOS' && 'brew update && brew install fish tcsh nushell' || true }} && \
4551
exit 0 || true;
4652
done
4753
exit 1

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ virtualenv.activate =
6666
fish = virtualenv.activation.fish:FishActivator
6767
powershell = virtualenv.activation.powershell:PowerShellActivator
6868
python = virtualenv.activation.python:PythonActivator
69+
nushell = virtualenv.activation.nushell:NushellActivator
6970
virtualenv.create =
7071
venv = virtualenv.create.via_global_ref.venv:Venv
7172
cpython3-posix = virtualenv.create.via_global_ref.builtin.cpython.cpython3:CPython3Posix
@@ -108,6 +109,7 @@ virtualenv.activation.bash = *.sh
108109
virtualenv.activation.batch = *.bat
109110
virtualenv.activation.cshell = *.csh
110111
virtualenv.activation.fish = *.fish
112+
virtualenv.activation.nushell = *.nu
111113
virtualenv.activation.powershell = *.ps1
112114
virtualenv.seed.wheels.embed = *.whl
113115

src/virtualenv/activation/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .batch import BatchActivator
55
from .cshell import CShellActivator
66
from .fish import FishActivator
7+
from .nushell import NushellActivator
78
from .powershell import PowerShellActivator
89
from .python import PythonActivator
910

@@ -14,4 +15,5 @@
1415
"PythonActivator",
1516
"BatchActivator",
1617
"FishActivator",
18+
"NushellActivator",
1719
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from __future__ import absolute_import, unicode_literals
2+
3+
import os
4+
5+
from virtualenv.util.path import Path
6+
from virtualenv.util.six import ensure_text
7+
8+
from ..via_template import ViaTemplateActivator
9+
10+
11+
class NushellActivator(ViaTemplateActivator):
12+
def templates(self):
13+
yield Path("activate.nu")
14+
yield Path("deactivate.nu")
15+
16+
def replacements(self, creator, dest_folder):
17+
# Due to nushell scoping, it isn't easy to create a function that will
18+
# deactivate the environment. For that reason a __DEACTIVATE_PATH__
19+
# replacement pointing to the deactivate.nu file is created
20+
21+
return {
22+
"__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt,
23+
"__VIRTUAL_ENV__": ensure_text(str(creator.dest)),
24+
"__VIRTUAL_NAME__": creator.env_name,
25+
"__BIN_NAME__": ensure_text(str(creator.bin_dir.relative_to(creator.dest))),
26+
"__PATH_SEP__": ensure_text(os.pathsep),
27+
"__DEACTIVATE_PATH__": ensure_text(str(Path(dest_folder) / "deactivate.nu")),
28+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Setting all environment variables for the venv
2+
let virtual-env = "__VIRTUAL_ENV__"
3+
let bin = "__BIN_NAME__"
4+
let path-sep = "__PATH_SEP__"
5+
6+
let old-path = ($nu.path | str collect ($path-sep))
7+
8+
let venv-path = ([$virtual-env $bin] | path join)
9+
let new-path = ($nu.path | prepend $venv-path | str collect ($path-sep))
10+
11+
# environment variables that will be batched loaded to the virtual env
12+
let new-env = ([
13+
[name, value];
14+
[PATH $new-path]
15+
[_OLD_VIRTUAL_PATH $old-path]
16+
[VIRTUAL_ENV $virtual-env]
17+
])
18+
19+
load-env $new-env
20+
21+
# Creating the new prompt for the session
22+
let virtual_prompt = (if ("__VIRTUAL_PROMPT__" != "") {
23+
"__VIRTUAL_PROMPT__"
24+
} {
25+
$virtual-env | path basename
26+
}
27+
)
28+
29+
# If there is no default prompt, then only the env is printed in the prompt
30+
let new_prompt = (if ( config | select prompt | empty? ) {
31+
($"build-string '(char lparen)' '($virtual_prompt)' '(char rparen) ' ")
32+
} {
33+
($"build-string '(char lparen)' '($virtual_prompt)' '(char rparen) ' (config get prompt | str find-replace "build-string" "")")
34+
})
35+
let-env PROMPT_COMMAND = $new_prompt
36+
37+
# We are using alias as the function definitions because only aliases can be
38+
# removed from the scope
39+
alias pydoc = python -m pydoc
40+
alias deactivate = source "__DEACTIVATE_PATH__"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Setting the old path
2+
let path-name = (if ((sys).host.name == "Windows") { "Path" } { "PATH" })
3+
let-env $path-name = $nu.env._OLD_VIRTUAL_PATH
4+
5+
# Unleting the environment variables that were created when activating the env
6+
unlet-env VIRTUAL_ENV
7+
unlet-env _OLD_VIRTUAL_PATH
8+
unlet-env PROMPT_COMMAND
9+
10+
unalias pydoc
11+
unalias deactivate

tests/unit/activation/test_nushell.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from __future__ import absolute_import, unicode_literals
2+
3+
import sys
4+
5+
if sys.version_info > (3,):
6+
from shutil import which
7+
else:
8+
from distutils.spawn import find_executable as which
9+
10+
11+
from virtualenv.activation import NushellActivator
12+
from virtualenv.info import IS_WIN
13+
14+
15+
def test_nushell(activation_tester_class, activation_tester):
16+
class Nushell(activation_tester_class):
17+
def __init__(self, session):
18+
cmd = which("nu")
19+
if cmd is None and IS_WIN:
20+
cmd = "c:\\program files\\nu\\bin\\nu.exe"
21+
22+
super(Nushell, self).__init__(NushellActivator, session, cmd, "activate.nu", "nu")
23+
24+
self.unix_line_ending = not IS_WIN
25+
26+
activation_tester(Nushell)

0 commit comments

Comments
 (0)