93a097f4bde80dc7af415cc0176489f25e1888ec

Author
Michael Aquilina <michaelaquilina@gmail.com>
Committer
GitHub <noreply@github.com>
Date

Message

Merge pull request #212 from MichaelAquilina/feat/better-uv-support

Add better support for uv projects

Diff

  1diff --git a/CHANGELOG.rst b/CHANGELOG.rst
  2index 5d0847806a93e843b4e624bdd63fd92306df2b74..2303a64a9d37ea4b44915c88e3fb301b3c9fbc5f 100644
  3--- a/CHANGELOG.rst
  4+++ b/CHANGELOG.rst
  5@@ -1,6 +1,11 @@
  6 Changelog
  7 =========
  8 
  9+3.8.0
 10+-----
 11+* Better support for uv projects
 12+* minor tweaks to default autoswitch message template
 13+
 14 3.7.1
 15 -----
 16 * only check python on precmd. Fixes issues with plugins like pyenv that load in PATH later to work correctly (#175)
 17diff --git a/autoswitch_virtualenv.plugin.zsh b/autoswitch_virtualenv.plugin.zsh
 18index d4e5b7ccaf2a9d87158c0b24f9f4b9fce804bcbe..7f9182c10d00ab1200090af29de6f58fc5112b36 100644
 19--- a/autoswitch_virtualenv.plugin.zsh
 20+++ b/autoswitch_virtualenv.plugin.zsh
 21@@ -54,6 +54,8 @@ function _get_venv_type() {
 22         venv_type="pipenv"
 23     elif [[ -f "$venv_dir/poetry.lock" ]]; then
 24         venv_type="poetry"
 25+    elif [[ -f "$venv_dir/uv.lock" ]]; then
 26+        venv_type="uv"
 27     elif [[ -f "$venv_dir/requirements.txt" || -f "$venv_dir/setup.py" ]]; then
 28         venv_type="virtualenv"
 29     fi
 30@@ -80,7 +82,7 @@ function _maybeworkon() {
 31     local venv_type="$2"
 32     local venv_name="$(_get_venv_name $venv_dir $venv_type)"
 33 
 34-    local DEFAULT_MESSAGE_FORMAT="Switching %venv_type: ${AUTOSWITCH_BOLD}${AUTOSWITCH_PURPLE}%venv_name${AUTOSWITCH_NORMAL} ${AUTOSWITCH_GREEN}[๐Ÿ%py_version]${AUTOSWITCH_NORMAL}"
 35+    local DEFAULT_MESSAGE_FORMAT="Switching to ${AUTOSWITCH_BOLD}%venv_type${AUTOSWITCH_NORMAL} project: ${AUTOSWITCH_BOLD}${AUTOSWITCH_PURPLE}%venv_name${AUTOSWITCH_NORMAL} ${AUTOSWITCH_GREEN}[๐Ÿ%py_version]${AUTOSWITCH_NORMAL}"
 36     if [[ "$LANG" != *".UTF-8" ]]; then
 37         # Remove multibyte characters if the terminal does not support utf-8
 38         DEFAULT_MESSAGE_FORMAT="${DEFAULT_MESSAGE_FORMAT/๐Ÿ/}"
 39@@ -121,13 +123,15 @@ function _check_path()
 40 {
 41     local check_dir="$1"
 42 
 43-    if [[ -e "${check_dir}/${AUTOSWITCH_FILE}" ]]; then
 44+    if [[ -f "${check_dir}/${AUTOSWITCH_FILE}" ]]; then
 45         printf "${check_dir}/${AUTOSWITCH_FILE}"
 46         return
 47     elif [[ -f "${check_dir}/poetry.lock" ]]; then
 48         printf "${check_dir}/poetry.lock"
 49     elif [[ -f "${check_dir}/Pipfile" ]]; then
 50         printf "${check_dir}/Pipfile"
 51+    elif [[ -f "${check_dir}/uv.lock" ]]; then
 52+        printf "${check_dir}/uv.lock"
 53     else
 54         # Abort search at file system root or HOME directory (latter is a performance optimisation).
 55         if [[ "$check_dir" = "/" || "$check_dir" = "$HOME" ]]; then
 56@@ -159,6 +163,14 @@ function _activate_pipenv() {
 57     return 1
 58 }
 59 
 60+function _activate_uv() {
 61+    if [[ -d ".venv" ]]; then
 62+        _maybeworkon ".venv" "uv"
 63+        return 0
 64+    fi
 65+    return 1
 66+}
 67+
 68 
 69 # Automatically switch virtualenv when $AUTOSWITCH_FILE file detected
 70 function check_venv()
 71@@ -197,6 +209,10 @@ function check_venv()
 72                 if type "poetry" > /dev/null && _activate_poetry; then
 73                     return
 74                 fi
 75+            elif [[ "$venv_path" == *"/uv.lock" ]]; then
 76+                if type "uv" > /dev/null && _activate_uv; then
 77+                    return
 78+                fi
 79             # standard use case: $venv_path is a file containing a virtualenv name
 80             elif [[ -f "$venv_path" ]]; then
 81                 local switch_to="$(<"$venv_path")"
 82@@ -246,6 +262,9 @@ function rmvenv()
 83     elif [[ "$venv_type" == "poetry" ]]; then
 84         deactivate
 85         poetry env remove "$(poetry run which python)"
 86+    elif [[ "$venv_type" == "uv" ]]; then
 87+        deactivate
 88+        rm -rf ".venv"
 89     else
 90         if [[ -f "$AUTOSWITCH_FILE" ]]; then
 91             local venv_name="$(<$AUTOSWITCH_FILE)"
 92@@ -318,6 +337,14 @@ function mkvenv()
 93         poetry install $params
 94         _activate_poetry
 95         return
 96+    elif [[ "$venv_type" == "uv" ]]; then
 97+        if ! type "uv" > /dev/null; then
 98+            _missing_error_message uv
 99+            return
100+        fi
101+        uv sync $params
102+        _activate_uv
103+        return
104     else
105         if ! type "virtualenv" > /dev/null; then
106             _missing_error_message virtualenv
107diff --git a/tests/test_check_path.zunit b/tests/test_check_path.zunit
108index f144d871984552ac57616aeee681624c53a83632..34e16a5a2a51d4c7d9347c96c97e342a723a21f8 100644
109--- a/tests/test_check_path.zunit
110+++ b/tests/test_check_path.zunit
111@@ -20,15 +20,6 @@
112     assert "$output" same_as "$TARGET/.venv"
113 }
114 
115-@test '_check_path - finds .venv directory in base directory' {
116-    mkdir "$TARGET/.venv"
117-
118-    run _check_path "$TARGET"
119-
120-    assert $state equals 0
121-    assert "$output" same_as "$TARGET/.venv"
122-}
123-
124 @test '_check_path - returns nothing if not found' {
125    run _check_path "$TARGET"
126 
127diff --git a/tests/test_check_venv.zunit b/tests/test_check_venv.zunit
128index 06a8583e24f8ce735ad9058fef4629e076b32dfd..c0017cc2b2c8b177ee6cc2c2909dd8fc5587658a 100644
129--- a/tests/test_check_venv.zunit
130+++ b/tests/test_check_venv.zunit
131@@ -131,7 +131,7 @@
132     run check_venv
133 
134     assert $status equals 0
135-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
136+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
137 }
138 
139 @test 'check_venv - No security warning for readable by group permission' {
140@@ -145,7 +145,7 @@
141     run check_venv
142 
143     assert $status equals 0
144-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
145+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
146 }
147 
148 @test 'check_venv - No security warning for readable only by owner permission' {
149@@ -158,7 +158,7 @@
150     run check_venv
151 
152     assert $status equals 0
153-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
154+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
155 }
156 
157 
158@@ -169,7 +169,7 @@
159     run check_venv
160 
161     assert $status equals 0
162-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoodefault\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
163+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoodefault\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
164 }
165 
166 @test 'check_venv - activate if .venv unavailable but poetry available' {
167@@ -184,7 +184,7 @@
168     run check_venv
169 
170     assert $status equals 0
171-    assert "$output" same_as "Switching poetry: \e[1m\e[35mpoetry-foo\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
172+    assert "$output" same_as "Switching to \e[1mpoetry\e[0m project: \e[1m\e[35mpoetry-foo\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
173 }
174 
175 @test 'check_venv - activate if .venv unavailable but pipenv available' {
176@@ -198,7 +198,7 @@
177     run check_venv
178 
179     assert $status equals 0
180-    assert "$output" same_as "Switching pipenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
181+    assert "$output" same_as "Switching to \e[1mpipenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
182 }
183 
184 
185@@ -239,17 +239,7 @@
186     run check_venv
187 
188     assert $status equals 0
189-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
190-}
191-
192-@test 'check_venv - works as intended with .venv directory available' {
193-    PWD="$TARGET"
194-    run virtualenv "$TARGET/.venv" --python=python3
195-
196-    run check_venv
197-
198-    assert $status equals 0
199-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35m.venv\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
200+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
201 }
202 
203 @test 'check_venv - works as intended with .venv directory not being virtualenv' {
204diff --git a/tests/test_maybeworkon.zunit b/tests/test_maybeworkon.zunit
205index 08ed4701204439928453a6789aa19c7ffd64d6eb..08a424e69cb7724f7e4bd438158a4a43c3165212 100644
206--- a/tests/test_maybeworkon.zunit
207+++ b/tests/test_maybeworkon.zunit
208@@ -52,7 +52,7 @@
209     run _maybeworkon "$TEST_VIRTUALENV" virtualenv
210 
211     assert $state equals 0
212-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
213+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
214 }
215 
216 @test '_maybeworkon - custom message' {
217@@ -72,7 +72,7 @@
218     run _maybeworkon "$TEST_VIRTUALENV" virtualenv
219 
220     assert $state equals 0
221-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[$PYTHON_VERSION]\e[0m"
222+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[$PYTHON_VERSION]\e[0m"
223 }
224 
225 @test '_maybeworkon - switches virtualenv if current virtualenv is different' {
226@@ -81,7 +81,7 @@
227     run _maybeworkon "$TEST_VIRTUALENV" virtualfoo
228 
229     assert $state equals 0
230-    assert "$output" contains "Switching virtualfoo: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
231+    assert "$output" contains "Switching to \e[1mvirtualfoo\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
232 }
233 
234 @test '_maybeworkon - switches virtualenv if current virtualenv is different (silent)' {
235@@ -107,5 +107,6 @@
236     run _maybeworkon hello-world-foo-de31f pipenv
237 
238     assert $state equals 0
239-    assert "$output" same_as "Switching pipenv: \e[1m\e[35mhello-world-foo\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
240+    assert "$output" same_as "Switching to \e[1mpipenv\e[0m project: \e[1m\e[35mhello-world-foo\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
241+
242 }
243diff --git a/tests/test_plugin.zunit b/tests/test_plugin.zunit
244index d3c6026e924f87b970c835a2ba9dd04b4561441d..64da1b5bedd80ee7d3564752c80ffbf7db9335eb 100644
245--- a/tests/test_plugin.zunit
246+++ b/tests/test_plugin.zunit
247@@ -67,7 +67,7 @@
248     run cd "$TEMP_DIR"
249 
250     assert $status equals 0
251-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
252+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
253 
254     mkdir "$TEMP_DIR/foo"
255 
256@@ -75,7 +75,7 @@
257     run cd "$TEMP_DIR/foo"
258 
259     assert $status equals 0
260-    assert "$output" same_as "Switching virtualenv: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
261+    assert "$output" same_as "Switching to \e[1mvirtualenv\e[0m project: \e[1m\e[35mfoobar\e[0m \e[32m[๐Ÿ$PYTHON_VERSION]\e[0m"
262 }
263 
264