Author tkhyn
Recipients tkhyn
Date 2017-05-23.00:47:03
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1495500424.56.0.88806724527.issue30436@psf.upfronthosting.co.za>
In-reply-to
Content
Hello, I stumbled upon this issue when using the module_has_submodule function in Django, which raised an exception when trying to import a dotted path such as ``parent.module`` when ``parent`` does not exist or is not a package. I would expect (as well as the django devs, apparently) find_spec to return None instead of raising an AttributeError or ModuleNotFoundError. 

Unless you think Django or any package making use of importlib.find_spec should handle these exceptions, the fix is quite simple.

Steps to reproduce (with Python 3.6.1):

touch parent.py
python3.6
>>> from importlib.util import find_spec
>>> find_spec('parent.module')
  File "C:\Python\3.6\Lib\importlib\util.py", line 89, in find_spec
    return _find_spec(fullname, parent.__path__)
AttributeError: module 'parent' has no attribute '__path__'
>>> find_spec('invalid_parent.module')
  File "C:\Python\3.6\Lib\importlib\util.py", line 88, in find_spec
    parent = __import__(parent_name, fromlist=['__path__'])
ModuleNotFoundError: No module named 'invalid_parent'

The fix is quite simple, replacing

    if fullname not in sys.modules:
        parent_name = fullname.rpartition('.')[0]
        if parent_name:
            # Use builtins.__import__() in case someone replaced it.

            parent = __import__(parent_name, fromlist=['__path__'])
            return _find_spec(fullname, parent.__path__)



        else:

            return _find_spec(fullname, None)
by:

    if fullname not in sys.modules:
        parent_name = fullname.rpartition('.')[0]
        if parent_name:
            # Use builtins.__import__() in case someone replaced it.
            try:
                parent = __import__(parent_name, fromlist=['__path__']).__path__

            except (AttributeError, ModuleNotFoundError):
                # parent is not a package
                return None
        else:
            parent = None
        return _find_spec(fullname, parent)


in importlib.util.find_spec.
History
Date User Action Args
2017-05-23 00:47:04tkhynsetrecipients: + tkhyn
2017-05-23 00:47:04tkhynsetmessageid: <1495500424.56.0.88806724527.issue30436@psf.upfronthosting.co.za>
2017-05-23 00:47:04tkhynlinkissue30436 messages
2017-05-23 00:47:03tkhyncreate