astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
26.44k stars 770 forks source link

UserWarning: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv #7466

Open kdheepak opened 1 month ago

kdheepak commented 1 month ago

On Windows, after running the following:

$ uv init --lib
$ uv add ipython --dev
$ source .venv/Scripts/activate
$ ipython

I get a warning:

$ ipython
C:\Users\USERNAME\gitrepos\project-foo\.venv\Lib\site-packages\IPython\core\interactiveshell.py:937: UserWarning: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
  warn(
Python 3.12.5 (main, Aug 14 2024, 04:23:18) [MSC v.1929 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.27.0 -- An enhanced Interactive Python. Type '?' for help.

This is with the latest version of uv:

$ uv --version
uv 0.4.10 (690716484 2024-09-13)
charliermarsh commented 1 month ago

Hmm, that's a surprising one. What does where ipython return?

kdheepak commented 1 month ago

Here's the output of where ipython:

$ where ipython
C:\Users\USERNAME\gitrepos\project-foo\.venv\Scripts\ipython.exe
C:\Users\USERNAME\miniforge3\Scripts\ipython.exe

fwiw, I'm using git bash. And which ipython returns the path/to/.venv/Scripts/ipython as well.

Oddly enough, uv run ipython doesn't give the warning.

danielhollas commented 1 month ago

I verified that this doesn't happen on Linux.

@kdheepak you could try to debug the issue by putting some print statements into C:\Users\USERNAME\gitrepos\project-foo\.venv\Lib\site-packages\IPython\core\interactiveshell.py

Specifically, it would be interesting to print out the value of variables paths and p_env in function init_virtualenv to find out why do following condition evaluates to False instead of True as it should.

  if any(p_venv == p.parents[1] for p in paths):                                                                             
     # Our exe is inside or has access to the virtualenv, don't need to do anything.
     return
kdheepak commented 1 month ago

I added the following print functions:

        print(f"{p_venv = }")
        print(f"{p.parents[1] = }")
        print(f"{p.parents = }")
        print(f"{paths = }")
        if any(p_venv == p.parents[1] for p in paths):
            # Our exe is inside or has access to the virtualenv, don't need to do anything.
            return

Here's the output:

p_venv = WindowsPath('/c/Users/USERNAME/gitrepos/project-foo/.venv')
p.parents[1] = WindowsPath('C:/Users/USERNAME/gitrepos/project-foo/.venv')
p.parents = <WindowsPath.parents>
paths = [WindowsPath('C:/Users/USERNAME/gitrepos/project-foo/.venv/Scripts/python.exe')]

The issue is because of Unix paths and Windows paths being compared. Adding a .resolve() doesn't appear like it'll solve it:

image
y5c4l3 commented 1 month ago

Cannot reproduce on Git Bash with version below:

$ uname -a
MINGW64_NT-10.0-19045 DESKTOP-14RM0I9 3.4.10-87d57229.x86_64 2024-02-14 20:17 UTC x86_64 Msys

Could you give more details in your virtualenv? Seems that your MSYS2 in Git Bash does not convert file paths presented in environment variables, where it should by default. Local result:

(testuv) ~/Documents/testuv
$ echo $VIRTUAL_ENV
/c/Users/y5/Documents/testuv/.venv
(testuv) ~/Documents/testuv
$ python -c 'import os; print(os.environ["VIRTUAL_ENV"])'
C:/Users/y5/Documents/testuv/.venv
kdheepak commented 1 month ago

Mine does the same thing:

$ echo $VIRTUAL_ENV
/c/Users/USERNAME/gitrepos/project-foo/.venv

$ python -c 'import os; print(os.environ["VIRTUAL_ENV"])'
C:/Users/USERNAME/gitrepos/project-foo/.venv

$ uname -a
MINGW64_NT-10.0-19045 XXXXXXX 3.4.10-2e2ef940.x86_64 2024-07-09 21:35 UTC x86_64 Msys

$ which uv
/c/Users/USERNAME/.cargo/bin/uv

$ deactivate

$ which python
/c/Users/USERNAME/miniforge3/python