Skip to content

bpo-39336: Allow packages to not let their child modules be set on them #18006

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

Merged
merged 8 commits into from
Jan 23, 2020

Conversation

DinoV
Copy link
Contributor

@DinoV DinoV commented Jan 14, 2020

This allows an import to proceed if a module raises AttributeError when attempting to set a child module on the parent package. This can occur if a loader wants to make its modules immutable, in which case the module cannot be set. In this case an ImportWarning is still logged in case this behavior is unexpected.

https://bugs.python.org/issue39336

DinoV and others added 2 commits January 14, 2020 17:49
Fix whitespace

Summary:

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:
@DinoV DinoV force-pushed the bpo_39336_error branch 2 times, most recently from 6e45545 to 862b536 Compare January 15, 2020 01:52
@brettcannon brettcannon self-requested a review January 15, 2020 18:35
try:
setattr(parent_module, child, module)
except AttributeError:
msg = (f"Can't set child package '{child}' on "
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
msg = (f"Can't set child package '{child}' on "
msg = (f"Cannot set an attribute on {parent!r} for child module {child!r}"

@@ -1339,6 +1342,39 @@ def test_circular_from_import(self):
str(cm.exception),
)

def test_unwritable_module(self):
package = inspect.cleandoc('''
Copy link
Member

Choose a reason for hiding this comment

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

Any reason to not put this as a module in test_import/data/?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, I just didn't realize that was a thing :)

@bedevere-bot
Copy link

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

@DinoV
Copy link
Contributor Author

DinoV commented Jan 16, 2020

I have made the requested changes; please review again.

@bedevere-bot
Copy link

Thanks for making the requested changes!

@brettcannon: please review the changes made to this pull request.

with open(os.path.join(os.path.dirname(path), 'x.py'), 'w+'):
pass

sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data'))
Copy link
Member

Choose a reason for hiding this comment

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

Why the path insertion instead of importing test.test_import.data.unwritable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was actually just following the pattern I saw in test_concurrency but this is certainly much cleaner!

finally:
del sys.modules['spam.x']

sys.modules['unwritable.x']
Copy link
Member

Choose a reason for hiding this comment

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

If this is delete the module then you can use a helper in test.support and register it with addCleanup().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, will do!

@bedevere-bot
Copy link

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

Copy link
Contributor Author

@DinoV DinoV left a comment

Choose a reason for hiding this comment

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

I have made the requested changes; please review again.

@brettcannon
Copy link
Member

Looks like Bedevere/GitHub hiccuped, so I manually updated the status for another review.

Copy link
Member

@brettcannon brettcannon left a comment

Choose a reason for hiding this comment

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

Two minor things to clean up, but I trust you to do that before you hit the green button. 😄

DinoV and others added 4 commits January 22, 2020 16:15
Remove unnecessary change in _ready_to_import
Remove white space change
@DinoV
Copy link
Contributor Author

DinoV commented Jan 23, 2020

Made one other small tweak to remove the change to _ready_to_import which was no longer necessary

@DinoV DinoV merged commit 9b6fec4 into python:master Jan 23, 2020
@DinoV DinoV deleted the bpo_39336_error branch January 23, 2020 00:42
@bedevere-bot
Copy link

@DinoV: Please replace # with GH- in the commit message next time. Thanks!

@bedevere-bot
Copy link

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot x86 Gentoo Installed with X 3.x has failed when building commit 9b6fec4.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/all/#builders/128/builds/181) and take a look at the build logs.
  4. Check if the failure is related to this commit (9b6fec4) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/all/#builders/128/builds/181

Failed tests:

  • test_import

Failed subtests:

  • test_unwritable_module - test.test_import.CircularImportTests

Summary of the results of the build (if available):

== Tests result: FAILURE then FAILURE ==

406 tests OK.

1 test failed:
test_import

13 tests skipped:
test_asdl_parser test_check_c_globals test_clinic test_devpoll
test_gdb test_ioctl test_kqueue test_msilib test_startfile
test_winconsoleio test_winreg test_winsound test_zipfile64

1 re-run test:
test_import

Total duration: 24 min 4 sec

Click to see traceback logs
TracebackTests) ... ok


Traceback (most recent call last):
  File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.9/test/test_import/__init__.py", line 1347, in test_unwritable_module
    import test.test_import.data.unwritable as unwritable
ModuleNotFoundError: No module named 'test.test_import.data.unwritable'

@pablogsal
Copy link
Member

Hummmm, seems that that buildbot failure is legitimate as this is the new test:

Traceback (most recent call last):
  File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.9/test/test_import/__init__.py", line 1347, in test_unwritable_module
    import test.test_import.data.unwritable as unwritable
ModuleNotFoundError: No module named 'test.test_import.data.unwritable'

@brettcannon
Copy link
Member

@DinoV I think you forgot to update the Makefile and Windows-related build files to add test/test_impor/data/unwritable directory to an installation.

shihai1991 pushed a commit to shihai1991/cpython that referenced this pull request Jan 31, 2020
…em (python#18006)

* bpo-39336: Allow setattr to fail on modules which aren't assignable

When attaching a child module to a package if the object in sys.modules raises an AttributeError (e.g. because it is immutable) it causes the whole import to fail.  This now allows immutable packages to exist and an ImportWarning is reported and the AttributeError exception is ignored.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants