99da1f7ccb8f7198f793684dc1beb01c66064c17
- Author
- Michael Aquilina <michaelaquilina@gmail.com>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/CHANGELOG.rst b/CHANGELOG.rst
2index 5b82ea2958e12beca62c07a73a744cca394ecdf2..9573f998dfee98ecd055a94372f38e186b056f79 100644
3--- a/CHANGELOG.rst
4+++ b/CHANGELOG.rst
5@@ -1,6 +1,11 @@
6 Changelog
7 =========
8
9+3.0.0
10+-----
11+* Improve integration support for poetry and pipenv. The ``mkvenv`` and ``rmvenv`` commands work as expected.
12+* Improve detection of poetry projects by looking for "poetry.lock" rather than "pyproject.toml"
13+
14 2.0.1
15 -----
16 * Fix issue where poetry would incorrectly try activate in projects with pyproject.toml but no poetry setup (Issue #130) (Thanks @hauntsaninja)
17diff --git a/README.rst b/README.rst
18index c04887800917d37247bf9dbac7797dd4be275fbe..2744beae5e36786299fa25168b1db09b09172078 100644
19--- a/README.rst
20+++ b/README.rst
21@@ -27,13 +27,18 @@ Simply call the ``mkvenv`` command in the directory you wish to setup a
22 virtual environment. A virtual environment specific to that folder will
23 now activate every time you enter it.
24
25-``zsh-autoswitch-virtualenv`` will try detect python projects and remind
26-you to create a virtual environment if e.g. setup.py or requirements.txt is
27-found in the current directory.
28+``zsh-autoswitch-virtualenv`` will detect python projects and remind
29+you to create a virtual environment. This mainly occurs if one of the following
30+is found in current the directory:
31
32-**NOTE: Pipenv and Poetry projects should not use 'mkvenv'.**
33+* setup.py
34+* requirements.txt
35+* Pipfile
36+* poetry.lock
37
38-**Use 'pipenv install' or 'poetry install' respectively instead**
39+To create a virtual environment for that project, simply run ``mkvenv``.
40+This command works as expected for all popular python project types
41+(virtualenvs, pipenv and poetry).
42
43 See the Commands_ section below for more detail.
44
45@@ -123,7 +128,7 @@ Commands
46 mkvenv
47 ''''''
48
49-Setup a new project with virtualenv autoswitching using the ``mkvenv``
50+Setup a new python project with autoswitching using the ``mkvenv``
51 helper command.
52
53 ::
54@@ -137,6 +142,8 @@ helper command.
55 Installing collected packages: requests
56 Successfully installed requests-2.11.1
57
58+This command also works as expected with both ``poetry`` and ``pipenv``.
59+
60 Optionally, you can specify the python binary to use for this virtual environment
61
62 ::
63@@ -144,40 +151,8 @@ Optionally, you can specify the python binary to use for this virtual environmen
64 $ mkvenv --python=/usr/bin/python3
65
66
67-It is also possible to inherit the system site packages (which can reduce duplication on the file system
68-and download/setup time).
69-
70-::
71-
72- $ mkvenv --system-site-packages
73-
74-In fact, ``mkvenv`` supports any parameters that can be passed to ``python -m virtualenv``.
75-A comprehensive list of options may be found in the
76-`virtualenv guide <https://virtualenv.pypa.io/en/latest/reference/#options>`__
77-
78-``mkvenv`` will create a virtual environment with the same name as the
79-current directory, suggest installing ``requirements.txt`` if available
80-and create the relevant ``.venv`` file for you.
81-
82-Next time you switch to that folder, you'll see the following message
83-
84-::
85-
86- $ cd my-python-project
87- Switching virtualenv: my-python-project [Python 3.4.3+]
88- $
89-
90-If you have set the ``AUTOSWITCH_DEFAULTENV`` environment variable,
91-exiting that directory will switch back to the value set.
92-
93-::
94-
95- $ cd ..
96- Switching virtualenv: mydefaultenv [Python 3.4.3+]
97- $
98-
99-Otherwise, ``deactivate`` will simply be called on the virtualenv to
100-switch back to the global python environment.
101+In fact any parameters passed to mkvenv will be passed to the relevant setup command.
102+The same applies to passing additional parameters to ``pipenv install`` and ``poetry install``.
103
104 Autoswitching is smart enough to detect that you have traversed to a
105 project subdirectory. So your virtualenv will not be deactivated if you
106@@ -216,6 +191,9 @@ This will delete the virtual environment in ``.venv`` and remove the
107 $ rmvenv
108 No .venv file in the current directory!
109
110+Similar to ``mkvenv``, the ``rmvenv`` command also works as you would
111+expect with removing ``poetry`` and ``pipenv`` projects.
112+
113 disable_autoswitch_virtualenv
114 '''''''''''''''''''''''''''''
115
116diff --git a/autoswitch_virtualenv.plugin.zsh b/autoswitch_virtualenv.plugin.zsh
117index 4f5e1f174b29529cf69bf9a3410db152cd7e4756..5742ddfa85e3ea59a92b8f7b9510bf270e2cee08 100644
118--- a/autoswitch_virtualenv.plugin.zsh
119+++ b/autoswitch_virtualenv.plugin.zsh
120@@ -1,4 +1,4 @@
121-export AUTOSWITCH_VERSION="2.0.1"
122+export AUTOSWITCH_VERSION="3.0.0"
123 export AUTOSWITCH_FILE=".venv"
124
125 RED="\e[31m"
126@@ -47,17 +47,16 @@ function _autoswitch_message() {
127 fi
128 }
129
130+
131 function _get_venv_type() {
132 local venv_dir="$1"
133 local venv_type="${2:-virtualenv}"
134 if [[ -f "$venv_dir/Pipfile" ]]; then
135 venv_type="pipenv"
136+ elif [[ -f "$venv_dir/poetry.lock" ]]; then
137+ venv_type="poetry"
138 elif [[ -f "$venv_dir/requirements.txt" || -f "$venv_dir/setup.py" ]]; then
139 venv_type="virtualenv"
140- # TODO: this is not technically correct as lots of tools use pyproject.toml
141- # however it's probably a good enough approximation for this function
142- elif [[ -f "$venv_dir/pyproject.toml" ]]; then
143- venv_type="poetry"
144 fi
145 printf "%s" "$venv_type"
146 }
147@@ -137,6 +136,34 @@ function _check_path()
148 }
149
150
151+function _activate_poetry() {
152+ # check if any environments exist before trying to activate
153+ # if env list is empty, then no environment exists that can be activated
154+ if [[ -n "$(poetry env list)" ]]; then
155+ # we need to infer the target virtualenv directory based on poetry's data
156+ # to easiest way is to actually get the location of the python binary and
157+ # infer the location of the virtualenv from there.
158+ if poetry_python=$(poetry run which python); then
159+ if venv_path="$(dirname $(dirname $poetry_python))"; then
160+ _maybeworkon "$venv_path" "poetry"
161+ return 0
162+ fi
163+ fi
164+ fi
165+ return 1
166+}
167+
168+
169+function _activate_pipenv() {
170+ # unfortunately running pipenv each time we are in a pipenv project directory is slow :(
171+ if venv_path="$(PIPENV_IGNORE_VIRTUALENVS=1 pipenv --venv 2>/dev/null)"; then
172+ _maybeworkon "$venv_path" "pipenv"
173+ return 0
174+ fi
175+ return 1
176+}
177+
178+
179 # Automatically switch virtualenv when $AUTOSWITCH_FILE file detected
180 function check_venv()
181 {
182@@ -175,39 +202,29 @@ function check_venv()
183 # check if Pipfile exists rather than invoking pipenv as it is slow
184 local pipfile_path="$(_check_path "$PWD" "Pipfile")"
185 # Same logic applies to poetry
186- local pyproject_path="$(_check_path "$PWD" "pyproject.toml")"
187+ local poetry_lock="$(_check_path "$PWD" "poetry.lock")"
188
189 if [[ -n "$pipfile_path" ]] && type "pipenv" > /dev/null; then
190- # unfortunately running pipenv each time we are in a pipenv project directory is slow :(
191- if venv_path="$(PIPENV_IGNORE_VIRTUALENVS=1 pipenv --venv 2>/dev/null)"; then
192- _maybeworkon "$venv_path" "pipenv"
193+ if _activate_pipenv; then
194 return
195 fi
196- elif [[ -n "$pyproject_path" ]] && type "poetry" > /dev/null; then
197- # we need to infer the target virtualenv directory based on poetry's data
198- # to easiest way is to actually get the location of the python binary and
199- # infer the location of the virtualenv from there.
200- if poetry_python=$(poetry run which python); then
201- if venv_path="$(dirname $(dirname $poetry_python))"; then
202- _maybeworkon "$venv_path" "poetry"
203- return
204- fi
205+ elif [[ -n "$poetry_lock" ]] && type "poetry" > /dev/null; then
206+ if _activate_poetry; then
207+ return
208 fi
209 fi
210
211 local venv_type="$(_get_venv_type "$PWD" "unknown")"
212
213 # If we still haven't got anywhere, fallback to defaults
214- if [[ "$venv_type" == "pipenv" ]]; then
215- printf "Python project detected. "
216- printf "Run ${PURPLE}pipenv install${NORMAL} to setup autoswitching\n"
217- elif [[ "$venv_type" == "virtualenv" ]]; then
218- printf "Python project detected. "
219+ if [[ "$venv_type" != "unknown" ]]; then
220diff --git a/tests/test_check_venv.zunit b/tests/test_check_venv.zunit
221index 4b3b17953e952afa7f9711a433205de18a316950..64ea4cc195ff4d557bde2b640595aabd156db86b 100644
222--- a/tests/test_check_venv.zunit
223+++ b/tests/test_check_venv.zunit
224@@ -36,7 +36,7 @@
225 run check_venv
226
227 assert $status equals 0
228- assert "$output" same_as "Python project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
229+ assert "$output" same_as "Python \e[35mvirtualenv\e[0m project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
230 }
231
232 @test 'check_venv - Displays message on project detection (setup.py)' {
233@@ -46,7 +46,7 @@
234 run check_venv
235
236 assert $status equals 0
237- assert "$output" same_as "Python project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
238+ assert "$output" same_as "Python \e[35mvirtualenv\e[0m project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
239 }
240
241 @test 'check_venv - Displays message on project detection (Pipfile)' {
242@@ -56,7 +56,17 @@
243 run check_venv
244
245 assert $status equals 0
246- assert "$output" same_as "Python project detected. Run \e[35mpipenv install\e[0m to setup autoswitching"
247+ assert "$output" same_as "Python \e[35mpipenv\e[0m project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
248+}
249+
250+@test 'check_venv - Displays message on project detection (poetry.lock)' {
251+ PWD="$TARGET"
252+ touch "$TARGET/poetry.lock"
253+
254+ run check_venv
255+
256+ assert $status equals 0
257+ assert "$output" same_as "Python \e[35mpoetry\e[0m project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
258 }
259
260 @test 'check_venv - Displays message on project detection (setup.py + requirements.txt)' {
261@@ -67,7 +77,7 @@
262 run check_venv
263
264 assert $status equals 0
265- assert "$output" same_as "Python project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
266+ assert "$output" same_as "Python \e[35mvirtualenv\e[0m project detected. Run \e[35mmkvenv\e[0m to setup autoswitching"
267 }
268
269 @test 'check_venv - Security warning for weak writeable by group permissions' {
270@@ -156,7 +166,7 @@
271
272 @test 'check_venv - activate if .venv unavailable but poetry available' {
273 PWD="$TARGET/sub-directory" # Should also work in subdirectories where pyproject.toml is found
274- touch "$TARGET/pyproject.toml"
275+ touch "$TARGET/poetry.lock"
276
277 # Mimic "poetry run which python"
278 function poetry {
279diff --git a/tests/test_get_venv_type.zunit b/tests/test_get_venv_type.zunit
280index f1817798740486c763095db36ba48da49ff9864a..f8e7b902fe9b8afc08708f96b1af5e9250ec2051 100644
281--- a/tests/test_get_venv_type.zunit
282+++ b/tests/test_get_venv_type.zunit
283@@ -18,6 +18,14 @@
284 assert "$output" same_as "pipenv"
285 }
286
287+@test '_get_venv_type poetry' {
288+ touch "$TARGET/poetry.lock"
289+
290+ run _get_venv_type "$TARGET"
291+
292+ assert $state equals 0
293+ assert "$output" same_as "poetry"
294+}
295
296 @test '_get_venv_type virtualenv (requirements.txt)' {
297 touch "$TARGET/requirements.txt"
298diff --git a/tests/test_mkvenv.zunit b/tests/test_mkvenv.zunit
299index 9b08b8eedcbe20946093e1368ab53cb6cf74cf6d..ae18ab4ebb5a6d1d080f9e5133fb717ccf9b63a4 100644
300--- a/tests/test_mkvenv.zunit
301+++ b/tests/test_mkvenv.zunit
302@@ -10,6 +10,22 @@
303 unset AUTOSWITCH_DEFAULT_REQUIREMENTS
304 TARGET="$(mktemp -d)"
305 cd "$TARGET"
306+
307+ function poetry {
308+ echo "poetry" $@
309+ }
310+
311+ function _activate_poetry {
312+ echo "activating poetry"
313+ }
314+
315+ function pipenv {
316+ echo "pipenv" $@
317+ }
318+
319+ function _activate_pipenv {
320+ echo "activating pipenv"
321+ }
322 }
323
324 @teardown {
325@@ -42,6 +58,30 @@
326 assert "$output" same_as "myproject"
327 }
328
329+@test 'mkvenv - (poetry project) runs correct command' {
330+ mkdir myproject
331+ cd myproject
332+ touch "poetry.lock"
333+
334+ run mkvenv
335+
336+ assert $status equals 0
337+ assert "$lines[1]" same_as "poetry install"
338+ assert "$lines[2]" same_as "activating poetry"
339+}
340+
341+@test 'mkvenv - (pipenv project) runs correct command' {
342+ mkdir myproject
343+ cd myproject
344+ touch "Pipfile"
345+
346+ run mkvenv
347+
348+ assert $status equals 0
349+ assert "$lines[1]" same_as "pipenv install --dev"
350+ assert "$lines[2]" same_as "activating pipenv"
351+}
352+
353 @test 'mkvenv - uses default python if set and not specified' {
354 mkdir myproject
355 cd myproject
356@@ -95,10 +135,54 @@
357 run mkvenv
358
359 assert $status equals 0
360- assert "$lines[1]" contains "zsh-autoswitch-virtualenv requires virtualenv to be installed!"
361+ assert "$lines[1]" contains "zsh-autoswitch-virtualenv requires 'virtualenv' to install this project!"
362 assert "$lines[2]" is_empty
363 assert "$lines[3]" contains "If this is already installed but you are still seeing this message,"
364 assert "$lines[4]" contains "then make sure the \e[1mvirtualenv\e[0m command is in your PATH.\n"
365 assert "$lines[5]" is_empty
366 assert ${#lines} equals 4
367 }
368+
369+@test 'prints help message and disables plugin if poetry not setup' {
370+ touch "poetry.lock"
371+
372+ # Mock type to fail
373+ function type() {
374+ if [[ "$1" == "poetry" ]]; then
375+ return 1
376+ fi
377+ return 0
378+ }
379+
380+ run mkvenv
381+
382+ assert $status equals 0
383+ assert "$lines[1]" contains "zsh-autoswitch-virtualenv requires 'poetry' to install this project!"
384+ assert "$lines[2]" is_empty
385+ assert "$lines[3]" contains "If this is already installed but you are still seeing this message,"
386+ assert "$lines[4]" contains "then make sure the \e[1mpoetry\e[0m command is in your PATH.\n"
387+ assert "$lines[5]" is_empty
388+ assert ${#lines} equals 4
389+}
390+
391+@test 'prints help message and disables plugin if pipenv not setup' {
392+ touch "Pipfile"
393+
394+ # Mock type to fail
395+ function type() {
396+ if [[ "$1" == "pipenv" ]]; then
397+ return 1
398+ fi
399+ return 0
400+ }
401+
402diff --git a/tests/test_rmvenv.zunit b/tests/test_rmvenv.zunit
403index 0e1b51df1ebc7c34fce96e0212e4824a95a496b8..c7fde66c80f7d479c6d00ed5db0c1e0c74598efc 100644
404--- a/tests/test_rmvenv.zunit
405+++ b/tests/test_rmvenv.zunit
406@@ -7,6 +7,18 @@
407 unset AUTOSWITCH_DEFAULT_REQUIREMENTS
408 TARGET="$(mktemp -d)"
409 cd "$TARGET"
410+
411+ function poetry {
412+ echo 'poetry' $@
413+ }
414+
415+ function pipenv {
416+ echo 'pipenv' $@
417+ }
418+
419+ function deactivate {
420+ echo 'deactivate'
421+ }
422 }
423
424 @teardown {
425@@ -64,3 +76,24 @@
426 test ! -f .venv
427 test ! -d "$HOME/.virtualenvs/$test_venv"
428 }
429+
430+@test 'rmvenv - uninstalls poetry project' {
431+ touch "poetry.lock"
432+
433+ run rmvenv
434+
435+ assert $state equals 0
436+ assert "$lines[1]" same_as "deactivate"
437+ assert "$lines[2]" same_as "poetry env remove poetry run which python"
438+}
439+
440+
441+@test 'rmvenv - uninstalls pipenv project' {
442+ touch "Pipfile"
443+
444+ run rmvenv
445+
446+ assert $state equals 0
447+ assert "$lines[1]" same_as "deactivate"
448+ assert "$lines[2]" same_as "pipenv --rm"
449+}