-
Notifications
You must be signed in to change notification settings - Fork 739
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
Update Windows trampolines for compatibility with Python 3.7 and earlier #8649
base: main
Are you sure you want to change the base?
Conversation
Thanks for contributing! Unfortunately, I also worked on the trampoline today and this will conflict with #8637 – I presume that can be reconciled though. I'm a +1 on this. We'll want to hear from @konstin as well. cc @samypr100 if you're interested, I know you've done a fair bit of work on the trampolines. |
I am a bit confused since I thought the trampolines were written when 3.7 was not EOL — did we break support at some point? |
I'm not sure, but at the time the trampoline in posy was created, 3.7 must have been somewhat old, so it may simply have gone unnoticed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm -1 on supporting Python 3.7. Python 3.7 was already EOL when uv was released, and users should upgrade asap rather than patching the support into tools. Otherwise the code looks good.
print_last_error_and_exit("Failed to set the file pointer to the start of zip EOCD"); | ||
}); | ||
|
||
let read_bytes = file_handle.read(&mut eocd_buf).unwrap_or_else(|_| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact instead?
|
||
// Size of the central directory (in bytes) | ||
let cd_size = u32::from_le_bytes(eocd_buf[12..16].try_into().unwrap_or_else(|_| { | ||
eprintln!("Slice length is not equal to 4 bytes"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be unreachable!()
Previously raised issue: #2445. I can verify uv fully works on Python 3.7 on Windows and the only issue remained is that trampoline issue. |
-1 for 3.7 support. |
That's correct both 3.7 and 3.8 EOL, but I think uv is still able to support them as in: uv/crates/uv-python/src/discovery.rs Lines 1767 to 1770 in 9fa4fea
|
One problem here is that I need to be able to sniff executables to tell if they're trampolines. I feel like that's trivial with the magic number at the end but kind of annoying here? If we're inverting the format I guess I'd expect
right? |
It would be difficult to put the magic number of the UV in a trivial position, since the magic number of the exe must be placed at the beginning of the file and the EOCD at the end. I think it is possible to insert the magic number in the last 2 bytes of the EOCD (where the length of the comment is stored). Whether this will work is implementation-dependent, but a normal zip implementation should work fine.
|
Yeah sorry, I forgot that there's the entire trampoline executable itself at the front.
We could hard-code this, I guess. Or pad to a specific size. I basically need to be able to inspect the trampoline, as in uv/crates/uv-trampoline-builder/src/lib.rs Lines 39 to 123 in 9cb7bcf
Notably with #8637 there isn't any zip payload at all in this variant, which perhaps simplifies things — we just won't be able to inspect the script variants. |
Anyway, I will read changes in #8637 . |
Generally speaking I'd assume you'd always want the magic at the |
If we parse the EOCD and read the magic number in the middle of the file, the probability of false positives is as low as with the current method (or more). |
One idea: In the case of UVSC, embedding "UV" in the comment length section of the EOCD and using the EOCD's magic number (PK\005\006) for detection allows for a robust and reliable method that only requires static reading. |
Summary
uv-trampoline uses Python's zipimport feature in a slightly hacky way to provide exe files, but the current method causes errors in Python 3.7 and earlier.
Specifically, uv-trampoline stores the Python executable path and other information as archive comments in the zip file. However, zipimport before Python 3.7 does not support archive comments (https://docs.python.org/3/library/zipimport.html#:~:text=Changed%20in%20version%203.8%3A%20Previously%2C%20ZIP%20archives%20with%20an%20archive%20comment%20were%20not%20supported ).
When I actually run the installed exe with Python 3.7 on Windows, I get the following puzzling error.
This PR will support Python 3.7 and earlier by moving the path to Python, etc. (as well as the exe file content) before the zip portion.
Is this necessary?
Of course, Python 3.7 is EOL.
But it is still used in practice and as long as it is installable with uv, it is a good thing to support it. The change to support it is simple and will not change the cost of maintenance much.
Also, if this change is unacceptable, I think we should display an error indicating that the exe is not supported in Python 3.7 or earlier. In that case I am still willing to create a PR.
Test Plan
Simply install and run some tool using Python 3.7.
I added this for now because I don't really understand the uv code based testing method, but I will fix it if there are any problems.