Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Lib/importlib/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,12 @@ def _find_and_load_unlocked(name, import_):
if parent:
# Set the module as an attribute on its parent.
parent_module = sys.modules[parent]
setattr(parent_module, name.rpartition('.')[2], module)
child = name.rpartition('.')[2]
try:
setattr(parent_module, child, module)
except AttributeError:
msg = f"Cannot set an attribute on {parent!r} for child module {child!r}"
_warnings.warn(msg, ImportWarning)
return module


Expand Down
22 changes: 21 additions & 1 deletion Lib/test/test_import/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import errno
import glob
import importlib.util
import inspect
Comment thread
DinoV marked this conversation as resolved.
Outdated
from importlib._bootstrap_external import _get_sourcefile
import marshal
import os
Expand All @@ -26,7 +27,7 @@
temp_dir, DirsOnSysPath)
from test.support import script_helper
from test.test_importlib.util import uncache

from types import ModuleType

skip_if_dont_write_bytecode = unittest.skipIf(
sys.dont_write_bytecode,
Expand All @@ -49,6 +50,8 @@ def _ready_to_import(name=None, source=""):
# reverts or removes the module when cleaning up
name = name or "spam"
with temp_dir() as tempdir:
if os.sep in name:
os.makedirs(os.path.join(tempdir, name.rpartition(os.sep)[0]))
path = script_helper.make_script(tempdir, name, source)
old_module = sys.modules.pop(name, None)
try:
Expand Down Expand Up @@ -1339,6 +1342,23 @@ def test_circular_from_import(self):
str(cm.exception),
)

def test_unwritable_module(self):
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data'))

Copy link
Copy Markdown
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
Copy Markdown
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!

try:
try:
import unwritable
with self.assertWarns(ImportWarning):
from unwritable import x

self.assertNotEqual(type(unwritable), ModuleType)
self.assertEqual(type(x), ModuleType)
with self.assertRaises(AttributeError):
unwritable.x = 42
finally:
sys.modules['unwritable.x']

Copy link
Copy Markdown
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
Copy Markdown
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!

sys.modules['unwritable']
finally:
del sys.path[0]

if __name__ == '__main__':
# Test needs to be a package, so we can do relative imports.
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_import/data/unwritable/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import sys

class MyMod(object):
__slots__ = ['__builtins__', '__cached__', '__doc__',
'__file__', '__loader__', '__name__',
'__package__', '__path__', '__spec__']
def __init__(self):
for attr in self.__slots__:
setattr(self, attr, globals()[attr])


sys.modules[__name__] = MyMod()
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Import loaders which publish immutable module objects can now publish immutable packages in addition to individual modules
Comment thread
DinoV marked this conversation as resolved.
Outdated
Loading