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

Resolve symlinks when determining if module is builtin #419

Merged
merged 1 commit into from
Jul 13, 2021

Conversation

benesch
Copy link
Contributor

@benesch benesch commented Jul 12, 2021

To determine whether a module is builtin, Dill compares mod.__file__
against sys.base_prefix. The former will have symlinks resolved, while
the latter will not. This causes builtin module detection to fail in
Python installations where sys.base_prefix involves symlinks, like
Homebrew-managed Python on macOS.

This commit resolves the issue by resolving symlinks in
sys.base_prefix before comparing module paths against it.

Fix #417.

To determine whether a module is builtin, Dill compares `mod.__file__`
against `sys.base_prefix`. The former will have symlinks resolved, while
the latter will not. This causes builtin module detection to fail in
Python installations where `sys.base_prefix` involves symlinks, like
Homebrew-managed Python on macOS.

This commit resolves the issue by resolving symlinks in
`sys.base_prefix` before comparing module paths against it.

Fix uqfoundation#417.
@mmckerns
Copy link
Member

LGTM

@mmckerns mmckerns merged commit 4bdc5df into uqfoundation:master Jul 13, 2021
@benesch benesch deleted the builtin-symlinks branch July 13, 2021 12:24
@benesch
Copy link
Contributor Author

benesch commented Jul 13, 2021

Thanks again for all your help tracking this down!

@mmckerns
Copy link
Member

Thx for the patch

@@ -1360,7 +1360,7 @@ def save_module(pickler, obj):
if hasattr(obj, "__file__"):
names = ["base_prefix", "base_exec_prefix", "exec_prefix",
"prefix", "real_prefix"]
builtin_mod = any(obj.__file__.startswith(os.path.normpath(getattr(sys, name)))
builtin_mod = any(obj.__file__.startswith(os.path.realpath(getattr(sys, name)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I just came across this PR because I ran into a similar issue. I tried to run with master but unfortunately, the problem doesn't go away fully. I tested a minor adjustment to the code. Is there any way you would consider putting in another minor fix for this, please? Use realpath on obj.__file__, too:

builtin_mod = any(os.path.realpath(obj.__file__).startswith(os.path.realpath(getattr(sys, name)))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. why don't you submit a PR?

@mmckerns mmckerns added this to the dill-0.3.5 milestone Apr 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Recursively pickling a function that references os fails in Python 3.9
3 participants