-
Notifications
You must be signed in to change notification settings - Fork 59
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
Tweaks for Windows portability #201
base: master
Are you sure you want to change the base?
Conversation
Don't assume we're running on a system with POSIX-style paths.
# Make copied file writeable if necessary. | ||
statinfo = os.stat(new_path) | ||
if not statinfo.st_mode & stat.S_IWRITE: | ||
os.chmod(new_path, statinfo.st_mode | stat.S_IWRITE) |
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 also be found in auditwheel
delocate/libsana.py
Outdated
@@ -40,7 +41,11 @@ class DependencyNotFound(Exception): | |||
""" | |||
|
|||
|
|||
def _filter_system_libs(libname: Text) -> bool: | |||
def filter_system_libs(libname: Text) -> bool: |
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 was duplicated between here and delocating.py
, so I removed the latter in favor of this copy.
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.
Moving filter_system_libs
like this technically breaks the API. Were you using it in your own library?
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.
Oh, that's a good point. Given the circular import issues between these to files, I guess I can just revert back to the duplication.
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 function is really showing its age by accepting a Text
input. I suspect it actually works with POSIX paths exclusively. Did something happen to cause this refactor?
I've very hesitant to accept a PR with os.path.splitdrive
.
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.
All of these changes are the result of repairing macOS wheels on a Windows host.
If I remember correctly, callers of filter_system_libs
are inquiring about, for example, C:\usr\lib\libSystem.B.dylib
- which obviously doesn't exist on the repairing host - but we can still consider it as a system library. So maybe the proper fix is elsewhere upstream.
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 very interested in learning what's putting C:
into C:\usr\lib\libSystem.B.dylib
.
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 can try to reproduce the issue again tomorrow. Unfortunately I don't actually have a Windows machine so it's a lot of pushing and waiting for CI. :(
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.
Well, since you've reopened this:
I'm very interested in learning what's putting C: into C:\usr\lib\libSystem.B.dylib.
It comes from here. On windows, realpath("foo") == "C:\\foo"
, where C:\
is the drive letter or UNC path of the current working directory. So if you chdir into \\myserver\shared_dir
, then realpath("foo") == "\\\\myserver\\shared_dir\\foo"
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.
Good work. I think realpath
should not be called on non-existing files in this case.
If I changed the return types for search_environment_for_lib
then I'd use Path
for existing files and PurePosixPath
for missing files.
Honestly I think the whole source should be converted to use |
This kind of stuff I want to revisit by adding Ruff's PTH rule. I don't want these outdated calls to be refactored into other outdated calls. |
Moving to I was interested to see that there are CI tests running on windows. I don't know the full history of this project but I guess there was some cross-platform consideration at some point. |
There are a few issues such as #29 and some others about using cross platform tools. I added Windows testing at least to keep track of which features were portable, but most of them rely on either MacOS tools or linkage. |
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.
Recommended reading: https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module
I don't think now is the time for a major refactor. Just fix what's absolutely needed.
delocate/delocating.py
Outdated
def posix_relpath(path: str, start: str = None) -> str: | ||
"""Return path relative to start using posix separators (/).""" | ||
rel = relpath(path, start) | ||
return Path(rel).as_posix() |
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.
If the goal is cross platform portability then do not use str
for path types in new functions.
delocate/delocating.py
Outdated
@@ -157,7 +165,7 @@ def _analyze_tree_libs( | |||
# @rpath, etc, at this point should never happen. | |||
raise DelocationError("%s was expected to be resolved." % required) | |||
r_ed_base = basename(required) | |||
if relpath(required, rp_root_path).startswith(".."): | |||
if Path(rp_root_path) not in Path(required).parents: |
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.
if Path(rp_root_path) not in Path(required).parents: | |
if not Path(required).is_relative_to(rp_root_path): |
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.
is_relative_to
is new in 3.9 and it looks like you're testing back to 3.7.
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.
Oops. That's easy to miss when I'm not using an IDE.
Python 3.8 EOL is this year. Maybe I can justify dropping support for it? The path in path.parents
syntax looks terrible even compared to relpath(...).startswith("..")
.
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 suppose one could say the syntax isn't great, but the docs do list root in path.parents
as equivalent to is_relative_to
.
delocate/libsana.py
Outdated
@@ -40,7 +41,11 @@ class DependencyNotFound(Exception): | |||
""" | |||
|
|||
|
|||
def _filter_system_libs(libname: Text) -> bool: | |||
def filter_system_libs(libname: Text) -> bool: |
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 function is really showing its age by accepting a Text
input. I suspect it actually works with POSIX paths exclusively. Did something happen to cause this refactor?
I've very hesitant to accept a PR with os.path.splitdrive
.
True Windows support is going to be a difficult task. It'll be far more complex than making sure paths work correctly. I suggest closing this for now and not worrying about Windows support for the foreseeable future. |
I apologize, but I'd like to put any Windows specific refactoring on hold for now. At least until certain Ruff rules are enforced and older versions of Python are dropped. |
You can still make a PR for refactors needed by |
This is true, but I've already tackled the more complicated stuff in Unless you're talking about delocating Windows dlls, for which there is already delvewheel. |
Then you've already finished the hardest parts. Never mind my pessimism, it sounds like you've got it handled. The reason I closed this is because your changes were causing readability and future refactoring concerns, such as I'm handing another large PR that I'd like to merge before working on this one. I'll reopen this to keep track of it, but it's possible that you may have to start over at a later time. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #201 +/- ##
==========================================
+ Coverage 96.45% 96.47% +0.02%
==========================================
Files 15 15
Lines 1184 1192 +8
==========================================
+ Hits 1142 1150 +8
Misses 42 42 ☔ View full report in Codecov by Sentry. |
This is the other half of the patch set I've been maintaining for
repairwheel
. Hopefully these changes are innocuous enough to push upstream.