Skip to content

Commit c872d47

Browse files
authored
Merge pull request #94 from Ableton/nre/master/2497-pyenv-windows
2 parents 10192cd + 0888d21 commit c872d47

4 files changed

Lines changed: 85 additions & 41 deletions

File tree

Jenkinsfile

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,11 @@ eventRecorder.timedStage('Integration Test') {
3838
String venvVersion = venv.run(returnStdout: true, script: 'python --version')
3939
assert venvVersion.startsWith('Python 3')
4040

41-
if (isUnix()) {
42-
echo 'Test VirtualEnv.createWithPyenv'
43-
Object pyvenv = pyenv.createVirtualEnv('3.10.3')
44-
String pyvenvVersion =
45-
pyvenv.run(returnStdout: true, script: 'python --version')
46-
echo pyvenvVersion
47-
assert pyvenvVersion.trim() == 'Python 3.10.3'
48-
}
41+
echo 'Test VirtualEnv.createWithPyenv'
42+
Object pyvenv = pyenv.createVirtualEnv('3.10.3')
43+
String pyvenvVersion = pyvenv.run(returnStdout: true, script: 'python --version')
44+
echo pyvenvVersion
45+
assert pyvenvVersion.trim() == 'Python 3.10.3'
4946
}
5047
}
5148
}

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.14.4
1+
0.15.0

src/com/ableton/Pyenv.groovy

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class Pyenv implements Serializable {
2323

2424
Pyenv(Object script, String pyenvRoot) {
2525
this.script = script
26-
this.pyenvRoot = pyenvRoot
26+
this.pyenvRoot = script.env.OS == 'Windows_NT' ?
27+
pyenvRoot.replace('\\', '/') : pyenvRoot
2728
}
2829

2930
/**
@@ -44,10 +45,6 @@ class Pyenv implements Serializable {
4445

4546
String trimmedPythonVersion = pythonVersion.trim()
4647

47-
if (script.env.OS == 'Windows_NT') {
48-
script.error 'This method is not supported on Windows'
49-
}
50-
5148
if (!versionSupported(trimmedPythonVersion)) {
5249
script.withEnv(["PYENV_ROOT=${pyenvRoot}"]) {
5350
String pyenvVersion = script.sh(
@@ -62,20 +59,31 @@ class Pyenv implements Serializable {
6259

6360
VirtualEnv venv = new VirtualEnv(script, randomSeed)
6461
script.retry(INSTALLATION_RETRIES) {
65-
List installCommands = [
66-
"export PYENV_ROOT=${pyenvRoot}",
67-
"export PATH=\$PYENV_ROOT/bin:\$PATH",
68-
'eval "\$(pyenv init --path)"',
69-
'eval "\$(pyenv init -)"',
70-
"pyenv install --skip-existing ${trimmedPythonVersion}",
71-
"pyenv shell ${trimmedPythonVersion}",
72-
'pip install virtualenv',
73-
"virtualenv ${venv.venvRootDir}",
74-
]
75-
venv.script.sh(
76-
label: "Install Python version ${trimmedPythonVersion} with pyenv",
77-
script: installCommands.join('\n') + '\n',
78-
)
62+
script.withEnv(["PYENV_VERSION=${trimmedPythonVersion}"]) {
63+
List installCommands = ["export PYENV_ROOT=${pyenvRoot}"]
64+
if (script.env.OS != 'Windows_NT') {
65+
installCommands += [
66+
"export PATH=\$PYENV_ROOT/bin:\$PATH",
67+
'eval "\$(pyenv init --path)"',
68+
'eval "\$(pyenv init -)"',
69+
]
70+
} else {
71+
String posixPyenvRoot = pyenvRoot[1] == ':' ?
72+
"/${pyenvRoot[0].toLowerCase()}/${pyenvRoot.substring(3)}" : pyenvRoot
73+
installCommands.add(
74+
"export PATH=${posixPyenvRoot}/shims:${posixPyenvRoot}/bin:\$PATH"
75+
)
76+
}
77+
installCommands += [
78+
"pyenv install --skip-existing ${trimmedPythonVersion}",
79+
'pyenv exec pip install virtualenv',
80+
"pyenv exec virtualenv ${venv.venvRootDir}",
81+
]
82+
venv.script.sh(
83+
label: "Install Python version ${trimmedPythonVersion} with pyenv",
84+
script: installCommands.join('\n') + '\n',
85+
)
86+
}
7987
}
8088

8189
return venv
@@ -93,10 +101,6 @@ class Pyenv implements Serializable {
93101
assertPyenvRoot()
94102
boolean result = false
95103

96-
if (script.env.OS == 'Windows_NT') {
97-
script.error 'This method is not supported on Windows'
98-
}
99-
100104
script.withEnv(["PYENV_ROOT=${pyenvRoot}"]) {
101105
String allVersions = script.sh(
102106
label: 'Get Python versions supported by Pyenv',

test/com/ableton/PyenvTest.groovy

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,26 @@ class PyenvTest extends BasePipelineTest {
101101

102102
@Test
103103
void createVirtualEnvWindows() {
104+
String pythonVersion = '1.2.3'
105+
String pyenvRoot = 'C:\\mock\\pyenv\\root'
106+
String posixPyenvRoot = '/c/mock/pyenv/root'
107+
String shPyenvRoot = 'C:/mock/pyenv/root'
108+
List shMocks = [
109+
new Tuple(installCommands(
110+
shPyenvRoot, pythonVersion, false, posixPyenvRoot), '', 0
111+
),
112+
new Tuple("${shPyenvRoot}/bin/pyenv install --list", '''Available versions:
113+
1.2.3
114+
''', 0),
115+
]
116+
shMocks.each { mock -> helper.addShMock(mock[0], mock[1], mock[2]) }
117+
helper.registerAllowedMethod('fileExists', [String]) { return true }
104118
script.env['OS'] = 'Windows_NT'
105119

106-
assertThrows(Exception) { new Pyenv(script, 'C:\\pyenv').createVirtualEnv('1.2.3') }
120+
Object venv = new Pyenv(script, pyenvRoot).createVirtualEnv(pythonVersion, 1)
121+
122+
assertEquals("/workspace/.venv/${TEST_RANDOM_NAME}" as String, venv.venvRootDir)
123+
shMocks.each { mock -> assertCallStackContains(mock[0]) }
107124
}
108125

109126
@Test
@@ -135,25 +152,51 @@ class PyenvTest extends BasePipelineTest {
135152

136153
assertTrue(new Pyenv(script, pyenvRoot).versionSupported('2.1.3'))
137154
assertFalse(new Pyenv(script, pyenvRoot).versionSupported('2.1.3333'))
155+
assertCallStackContains("${pyenvRoot}/bin/pyenv install --list")
138156
}
139157

140158
@Test
141159
void versionSupportedWindows() {
160+
// Resembles pyenv's output, at least as of version 2.3.x
161+
String mockPyenvVersions = '''Available versions:
162+
2.1.3
163+
2.2.3
164+
2.3.7
165+
'''
166+
String shPyenvRoot = 'C:/pyenv'
167+
helper.addShMock("${shPyenvRoot}/bin/pyenv install --list", mockPyenvVersions, 0)
168+
helper.registerAllowedMethod('fileExists', [String]) { return true }
142169
script.env['OS'] = 'Windows_NT'
143170

144-
assertThrows(Exception) { new Pyenv(script, 'C:\\pyenv').versionSupported('1.2.3') }
171+
assertTrue(new Pyenv(script, shPyenvRoot).versionSupported('2.1.3'))
172+
assertFalse(new Pyenv(script, shPyenvRoot).versionSupported('2.1.3333'))
173+
assertCallStackContains("${shPyenvRoot}/bin/pyenv install --list")
145174
}
146175

147-
private String installCommands(String pyenvRoot, String pythonVersion) {
176+
private String installCommands(
177+
String pyenvRoot,
178+
String pythonVersion,
179+
boolean isUnix = true,
180+
String posixPyenvRoot = null
181+
) {
148182
List installCommands = [
149183
"export PYENV_ROOT=${pyenvRoot}",
150-
"export PATH=\$PYENV_ROOT/bin:\$PATH",
151-
'eval "\$(pyenv init --path)"',
152-
'eval "\$(pyenv init -)"',
184+
]
185+
if (isUnix) {
186+
installCommands += [
187+
"export PATH=\$PYENV_ROOT/bin:\$PATH",
188+
'eval "\$(pyenv init --path)"',
189+
'eval "\$(pyenv init -)"',
190+
]
191+
} else {
192+
installCommands += [
193+
"export PATH=${posixPyenvRoot}/shims:${posixPyenvRoot}/bin:\$PATH",
194+
]
195+
}
196+
installCommands += [
153197
"pyenv install --skip-existing ${pythonVersion}",
154-
"pyenv shell ${pythonVersion}",
155-
'pip install virtualenv',
156-
"virtualenv /workspace/.venv/${TEST_RANDOM_NAME}",
198+
'pyenv exec pip install virtualenv',
199+
"pyenv exec virtualenv /workspace/.venv/${TEST_RANDOM_NAME}",
157200
]
158201

159202
return installCommands.join('\n') + '\n'

0 commit comments

Comments
 (0)