Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: symbolic link to the exe created by uv can not work #1766

Closed
j178 opened this issue Feb 20, 2024 · 5 comments · Fixed by #1803
Closed

Windows: symbolic link to the exe created by uv can not work #1766

j178 opened this issue Feb 20, 2024 · 5 comments · Fixed by #1803
Assignees
Labels
bug Something isn't working windows Specific to the Windows platform

Comments

@j178
Copy link
Contributor

j178 commented Feb 20, 2024

Information

System: Windows 11 (x86_64)
Shell: PowerShell 7
uv version: uv 0.1.5

The original issue is from astral-sh/rye#696.
Rye creates symbolic links to installed script under ~/.rye/shims, but the script created by uv can not work. The default pip-tools created script works fine.

Steps to reproduce

> uv --version
uv 0.1.5

> uv -v venv -p C:\Users\nigel\.rye\py\cpython@3.12.1\install\python.exe
 uv_interpreter::python_query::find_requested_python request="C:\\Users\\nigel\\.rye\\py\\cpython@3.12.1\\install\\python.exe", platform=Platform { os: Windows, arch: X86_64 }, cache=Cache { root: "\\\\?\\C:\\Users\\nigel\\AppData\\Local\\uv\\cache", refresh: None, _temp_dir_drop: None }
      0.002273s   0ms DEBUG uv_interpreter::interpreter Using cached markers for: \\?\C:\Users\nigel\.rye\py\cpython@3.12.1\install\python.exe
Using Python 3.12.1 interpreter at C:\Users\nigel\.rye\py\cpython@3.12.1\install\python.exe
Creating virtualenv at: .venv

> uv -v pip install pycowsay
 uv::requirements::from_source source=pycowsay
    0.002195s DEBUG uv_interpreter::virtual_env Found a virtualenv named .venv at: E:\tmp\test-uv\.venv
    0.002394s DEBUG uv_interpreter::interpreter Detecting markers for: \\?\E:\tmp\test-uv\.venv\Scripts\python.exe
    0.256957s DEBUG uv::commands::pip_install Using Python 3.12.1 environment at E:\tmp\test-uv\.venv\Scripts\python.exe
 uv_client::flat_index::from_entries
 uv_resolver::resolver::solve
      0.261629s   0ms DEBUG uv_resolver::resolver Solving with target Python version 3.12.1
   uv_resolver::resolver::choose_version package=root
   uv_resolver::resolver::get_dependencies package=root, version=0a0.dev0
        0.261995s   0ms DEBUG uv_resolver::resolver Adding direct dependency: pycowsay*
   uv_resolver::resolver::choose_version package=pycowsay
     uv_resolver::resolver::package_wait package_name=pycowsay
 uv_resolver::resolver::process_request request=Versions pycowsay
   uv_client::registry_client::simple_api package=pycowsay
     uv_client::cached_client::get_cacheable
       uv_client::cached_client::read_and_parse_cache file=\\?\C:\Users\nigel\AppData\Local\uv\cache\simple-v1\pypi\pycowsay.rkyv
 uv_resolver::resolver::process_request request=Prefetch pycowsay *
          0.262916s   0ms DEBUG uv_client::cached_client Found stale response for: https://pypi.org/simple/pycowsay/
          0.262970s   0ms DEBUG uv_client::cached_client Sending revalidation request for: https://pypi.org/simple/pycowsay/
       uv_client::cached_client::revalidation_request url="https://pypi.org/simple/pycowsay/"
          0.761721s 499ms DEBUG uv_client::cached_client Found not-modified response for: https://pypi.org/simple/pycowsay/
       uv_client::cached_client::refresh_cache file=\\?\C:\Users\nigel\AppData\Local\uv\cache\simple-v1\pypi\pycowsay.rkyv
 uv_resolver::version_map::from_metadata
   uv_distribution::distribution_database::get_or_build_wheel_metadata dist=pycowsay==0.0.0.2
     uv_client::registry_client::wheel_metadata built_dist=pycowsay==0.0.0.2
       uv_client::cached_client::get_serde
         uv_client::cached_client::get_cacheable
           uv_client::cached_client::read_and_parse_cache file=\\?\C:\Users\nigel\AppData\Local\uv\cache\wheels-v0\pypi\pycowsay\pycowsay-0.0.0.2-py3-none-any.msgpack
        0.764071s 501ms DEBUG uv_resolver::resolver Searching for a compatible version of pycowsay (*)
        0.764190s 502ms DEBUG uv_resolver::resolver Selecting: pycowsay==0.0.0.2 (pycowsay-0.0.0.2-py3-none-any.whl)
   uv_resolver::resolver::get_dependencies package=pycowsay, version=0.0.0.2
     uv_resolver::resolver::distributions_wait package_id=pycowsay-0.0.0.2
              0.764488s   0ms DEBUG uv_client::cached_client Found fresh response for: https://files.pythonhosted.org/packages/eb/bd/17f894b13037499e615048a6daeb9cae28142ee85ce6eb8d24d10504860b/pycowsay-0.0.0.2-py3-none-any.whl
Resolved 1 package in 503ms
    0.765456s DEBUG uv_installer::plan Requirement already cached: pycowsay==0.0.0.2
 uv_installer::installer::install num_wheels=1
Installed 1 package in 9ms
 + pycowsay==0.0.0.2

# Create a symbolic link to pycowsay
> New-Item -Path .\pycatsay.exe -ItemType SymbolicLink -Value .\.venv\Scripts\pycowsay.exe

    Directory: E:\tmp\test-uv

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
la---           2024/2/21     0:47              0 pycatsay.exe -> .\.venv\Scripts\pycowsay.exe

> .\pycatsay.exe
Error: The system cannot find the file specified.
 (from CreateProcessA(null(), child_cmdline.into_bytes_with_nul().as_mut_ptr(),
    null(), null(), 1, 0, null(), null(), addr_of!(*si),
    child_process_info.as_mut_ptr()))
@MichaReiser
Copy link
Member

Thanks for reporting. Hmm, that's going to be interesting. What I understand from the error is that our shim fails to locate the pyton.exe path because it searches it relative to the executed command. We may need to check if the file is a symlink before resolving the python exe.

@MichaReiser MichaReiser added bug Something isn't working windows Specific to the Windows platform labels Feb 20, 2024
@konstin
Copy link
Member

konstin commented Feb 20, 2024

On unix we use the absolute path as interpreter, maybe we can embed it in the binary too. Otherwise we need to find a solution that works with symlinks, junctions and hardlinks (as far as these work with exes at all).

@j178
Copy link
Contributor Author

j178 commented Feb 20, 2024

On unix we use the absolute path as interpreter, maybe we can embed it in the binary too.

Yes, I agree this should be the best solution.

@MichaReiser
Copy link
Member

On unix we use the absolute path as interpreter, maybe we can embed it in the binary too. Otherwise we need to find a solution that works with symlinks, junctions and hardlinks (as far as these work with exes at all).

I considered searching for the shebang of the script and use that hehe. But it would require unzipping the script. I don't know if there's another way to embed it except if we manipulate the binary in place which sounds scary

@mitsuhiko
Copy link
Contributor

It looks like setuptools own launcher executable "parses" the shebang.

https://github.com/pypa/setuptools/blob/569fd7b0b587409f4043f127a766131a25b366dd/launcher.c#L293-L298

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working windows Specific to the Windows platform
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants