-
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?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -7,6 +7,7 @@ | |||||
import logging | ||||||
import os | ||||||
import shutil | ||||||
import stat | ||||||
import warnings | ||||||
from os.path import abspath, basename, dirname, exists, realpath, relpath | ||||||
from os.path import join as pjoin | ||||||
|
@@ -28,6 +29,7 @@ | |||||
|
||||||
from .libsana import ( | ||||||
_allow_all, | ||||||
filter_system_libs, | ||||||
get_rp_stripper, | ||||||
stripped_lib_dict, | ||||||
tree_libs, | ||||||
|
@@ -56,6 +58,12 @@ class DelocationError(Exception): | |||||
pass | ||||||
|
||||||
|
||||||
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() | ||||||
|
||||||
|
||||||
def delocate_tree_libs( | ||||||
lib_dict: Mapping[Text, Mapping[Text, Text]], | ||||||
lib_path: Text, | ||||||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||||||
# Not local, plan to copy | ||||||
if r_ed_base in copied_basenames: | ||||||
raise DelocationError( | ||||||
|
@@ -202,6 +210,10 @@ def _copy_required_libs( | |||||
"Copying library %s to %s", old_path, relpath(new_path, root_path) | ||||||
) | ||||||
shutil.copy(old_path, new_path) | ||||||
# 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) | ||||||
Comment on lines
+220
to
+223
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can also be found in auditwheel |
||||||
# Delocate this file now that it is stored locally. | ||||||
needs_delocating.add(new_path) | ||||||
# Update out_lib_dict with the new file paths. | ||||||
|
@@ -224,7 +236,7 @@ def _update_install_names( | |||||
for required in files_to_delocate: | ||||||
# Set relative path for local library | ||||||
for requiring, orig_install_name in lib_dict[required].items(): | ||||||
req_rel = relpath(required, dirname(requiring)) | ||||||
req_rel = posix_relpath(required, dirname(requiring)) | ||||||
new_install_name = "@loader_path/" + req_rel | ||||||
if orig_install_name == new_install_name: | ||||||
logger.info( | ||||||
|
@@ -401,10 +413,6 @@ def _dylibs_only(filename: str) -> bool: | |||||
return filename.endswith(".so") or filename.endswith(".dylib") | ||||||
|
||||||
|
||||||
def filter_system_libs(libname: str) -> bool: | ||||||
return not (libname.startswith("/usr/lib") or libname.startswith("/System")) | ||||||
|
||||||
|
||||||
def _delocate_filter_function( | ||||||
path: str, | ||||||
*, | ||||||
|
@@ -701,7 +709,7 @@ def delocate_wheel( | |||||
] | ||||||
_make_install_name_ids_unique( | ||||||
libraries=libraries_in_lib_path, | ||||||
install_id_prefix=DLC_PREFIX + relpath(lib_sdir, wheel_dir), | ||||||
install_id_prefix=DLC_PREFIX + posix_relpath(lib_sdir, wheel_dir), | ||||||
) | ||||||
rewrite_record(wheel_dir) | ||||||
if len(copied_libs) or not in_place: | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
import warnings | ||
from os.path import basename, dirname, realpath | ||
from os.path import join as pjoin | ||
from pathlib import Path | ||
from typing import ( | ||
Callable, | ||
Dict, | ||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. This was duplicated between here and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. This function is really showing its age by accepting a I've very hesitant to accept a PR with There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm very interested in learning what's putting There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Well, since you've reopened this:
It comes from here. On windows, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good work. I think If I changed the return types for |
||
"""Return True if libname starts with /System or /usr/lib.""" | ||
# If libname has a drive letter, we need to strip it off first. | ||
_, libname = os.path.splitdrive(libname) | ||
libname = Path(libname).as_posix() | ||
return not (libname.startswith("/usr/lib") or libname.startswith("/System")) | ||
|
||
|
||
|
@@ -91,7 +96,7 @@ def get_dependencies( | |
logger.debug("Ignoring dependencies of %s" % lib_fname) | ||
return | ||
if not os.path.isfile(lib_fname): | ||
if not _filter_system_libs(lib_fname): | ||
if not filter_system_libs(lib_fname): | ||
logger.debug( | ||
"Ignoring missing library %s because it is a system library.", | ||
lib_fname, | ||
|
@@ -111,7 +116,7 @@ def get_dependencies( | |
else: | ||
dependency_path = search_environment_for_lib(install_name) | ||
if not os.path.isfile(dependency_path): | ||
if not _filter_system_libs(dependency_path): | ||
if not filter_system_libs(dependency_path): | ||
logger.debug( | ||
"Skipped missing dependency %s" | ||
" because it is a system library.", | ||
|
@@ -327,7 +332,7 @@ def _tree_libs_from_libraries( | |
def tree_libs_from_directory( | ||
start_path: str, | ||
*, | ||
lib_filt_func: Callable[[str], bool] = _filter_system_libs, | ||
lib_filt_func: Callable[[str], bool] = filter_system_libs, | ||
copy_filt_func: Callable[[str], bool] = lambda path: True, | ||
executable_path: Optional[str] = None, | ||
ignore_missing: bool = False, | ||
|
@@ -754,7 +759,7 @@ def wheel_libs( | |
When dependencies can not be located and `ignore_missing` is False. | ||
""" | ||
if filt_func is None: | ||
filt_func = _filter_system_libs | ||
filt_func = filter_system_libs | ||
with TemporaryDirectory() as tmpdir: | ||
zip2dir(wheel_fname, tmpdir) | ||
lib_dict = tree_libs_from_directory( | ||
|
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.