{"action":"created","issue":{"url":"https://api.github.com/repos/IronLanguages/main/issues/1202","labels_url":"https://api.github.com/repos/IronLanguages/main/issues/1202/labels{/name}","comments_url":"https://api.github.com/repos/IronLanguages/main/issues/1202/comments","events_url":"https://api.github.com/repos/IronLanguages/main/issues/1202/events","html_url":"https://github.com/IronLanguages/main/issues/1202","id":78986534,"number":1202,"title":"Ironpython issue with import hook subpackage/submodule PEP302","user":{"login":"macsec","id":12534774,"avatar_url":"https://avatars.githubusercontent.com/u/12534774?v=3","gravatar_id":"","url":"https://api.github.com/users/macsec","html_url":"https://github.com/macsec","followers_url":"https://api.github.com/users/macsec/followers","following_url":"https://api.github.com/users/macsec/following{/other_user}","gists_url":"https://api.github.com/users/macsec/gists{/gist_id}","starred_url":"https://api.github.com/users/macsec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/macsec/subscriptions","organizations_url":"https://api.github.com/users/macsec/orgs","repos_url":"https://api.github.com/users/macsec/repos","events_url":"https://api.github.com/users/macsec/events{/privacy}","received_events_url":"https://api.github.com/users/macsec/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-05-21T13:03:04Z","updated_at":"2015-05-21T20:24:42Z","closed_at":null,"body":"I think I may have found a bug with IronPython's implmentation of import hooking as defined in <a href=\"https://www.python.org/dev/peps/pep-0302/\">PEP302</a>\r\n\r\nThe issue I am facing is when trying to apply import hooks using sys.meta_path or sys.path_hooks. IronPython seems to properly call my hooks when importing simple modules and packages. If I attempt to import a submodule or package such as foo.bar the hook is called to import foo but the hook is not called when attempting to import bar.\r\n\r\nI have created the below code to replicate the issue. When run in CPython this same code does not suffer any issues.\r\n\r\n```python\r\nimport imp\r\nimport sys\r\n\r\nclass ReflectiveLoader2(object):\r\n\r\ndef __init__(self):\r\n    print \"Init RL2\"\r\n\r\ndef find_module(self, fullname, path=None):\r\n    print \"find_module_RL2 called with fullname %s and path %s\" % (fullname, path)\r\n    self.path = path\r\n    return self\r\n\r\ndef load_module(self, fullname):\r\n    print \"load_module_RL2 called with fullname %s\" % fullname\r\n\r\n    mod = imp.new_module(fullname)\r\n    mod.__name__ = fullname\r\n    mod.__loader__ = self\r\n    #Simulate a couple scenarios for imports\r\n    #Simulate a method\r\n    if fullname == \"foo\":\r\n        print \"its foo\"\r\n        mod.__filepath__ = r\"C:\\not\\a\\real\\path\\foo.py\"\r\n        source = \"def fooFunction(thing):print thing*3\"\r\n\r\n    #Simulate another method\r\n    elif fullname == \"bar\":\r\n        print \"its bar\"\r\n        mod.__filepath__ = r\"C:\\not\\a\\real\\path\\bar.py\"\r\n        source = \"def barFunction(thing):print thing*4\"\r\n\r\n    #Simulate package\r\n    elif fullname == \"baz\":\r\n        print \"its baz\"\r\n        mod.__filepath__ = r\"C:\\not\\a\\real\\path\\baz\\__init__.py\"\r\n        mod.__path__ = r\"C:\\not\\a\\real\\path\\baz\"\r\n        source = \"print 'initializing baz stuff here'\"\r\n\r\n    #Simulate subpackage\r\n    elif fullname == \"baz.bat\":\r\n        print \"its baz.bat\"\r\n        mod.__filepath__ = r\"C:\\not\\a\\real\\path\\baz\\bat.py\"\r\n        mod.__path__ = r\"C:\\not\\a\\real\\path\\baz\"\r\n            source = \"def Batfunc():print 'in baz.bat sub package'\"\r\n\r\n    #catchall\r\n    else:\r\n        print \"Not foo, bar or baz its %s\" % fullname\r\n        source = \"\"\r\n\r\n    exec source in mod.__dict__\r\n    return mod\r\n\r\n\r\nsys.meta_path = [ReflectiveLoader2()]\r\n\r\nimport foo\r\nfoo.fooFunction(\"ABC\")\r\n\r\nimport bar\r\nbar.barFunction(\"DEF\")\r\n\r\nimport baz.bat\r\nbaz.bat.Batfunc()\r\n```\r\n\r\nHere is the output from the above code using both IronPython and CPython. I have run this code on two seperate systems just in case the install was bad on one of them\r\n\r\n```\r\nC:\\Users\\Administrator\\project>\"C:\\Program Files (x86)\\IronPython 2.7\\ipy.exe\" ReflectiveLoader2.py\r\n    Init RL2\r\n    find_module_RL2 called with fullname foo and path None\r\n    load_module_RL2 called with fullname foo\r\n    its foo\r\n    ABCABCABC\r\n    find_module_RL2 called with fullname bar and path None\r\n    load_module_RL2 called with fullname bar\r\n    its bar\r\n    DEFDEFDEFDEF\r\n    find_module_RL2 called with fullname baz and path None\r\n    load_module_RL2 called with fullname baz\r\n    its baz\r\n    initializing baz stuff here\r\n\r\n    Traceback (most recent call last):\r\n        File \"ReflectiveLoader2.py\", line 63, in <module>\r\n        ImportError: No module named bat\r\n\r\n C:\\Users\\Administrator\\project>C:\\Python27\\python.exe ReflectiveLoader2.py\r\n    Init RL2\r\n    find_module_RL2 called with fullname foo and path None\r\n    load_module_RL2 called with fullname foo\r\n    its foo\r\n    ABCABCABC\r\n    find_module_RL2 called with fullname bar and path None\r\n    load_module_RL2 called with fullname bar\r\n    its bar\r\n    DEFDEFDEFDEF\r\n    find_module_RL2 called with fullname baz and path None\r\n    load_module_RL2 called with fullname baz\r\n    its baz\r\n    initializing baz stuff here\r\n    find_module_RL2 called with fullname baz.bat and path C:\\not\\a\\real\\path\\baz\r\n    load_module_RL2 called with fullname baz.bat\r\n    its baz.bat\r\n    in baz.bat sub package\r\n```"},"comment":{"url":"https://api.github.com/repos/IronLanguages/main/issues/comments/104411407","html_url":"https://github.com/IronLanguages/main/issues/1202#issuecomment-104411407","issue_url":"https://api.github.com/repos/IronLanguages/main/issues/1202","id":104411407,"user":{"login":"macsec","id":12534774,"avatar_url":"https://avatars.githubusercontent.com/u/12534774?v=3","gravatar_id":"","url":"https://api.github.com/users/macsec","html_url":"https://github.com/macsec","followers_url":"https://api.github.com/users/macsec/followers","following_url":"https://api.github.com/users/macsec/following{/other_user}","gists_url":"https://api.github.com/users/macsec/gists{/gist_id}","starred_url":"https://api.github.com/users/macsec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/macsec/subscriptions","organizations_url":"https://api.github.com/users/macsec/orgs","repos_url":"https://api.github.com/users/macsec/repos","events_url":"https://api.github.com/users/macsec/events{/privacy}","received_events_url":"https://api.github.com/users/macsec/received_events","type":"User","site_admin":false},"created_at":"2015-05-21T20:24:42Z","updated_at":"2015-05-21T20:24:42Z","body":"After some additional troubleshooting I think this was mostly operator error. It apears CPython is slightly more forgiving in terms of a module's \\__path__ attribute. If the above code is changed so that\r\n```python\r\nmod.__path__ = r\"C:\\not\\a\\real\\path\\baz\"\r\n```\r\nLooks like\r\n```python\r\nmod.__path__ = [r\"C:\\not\\a\\real\\path\\baz\",]\r\n```\r\nEverything works fine.\r\n\r\nIronPython is expecting a List and when given a string it silently fails to handle it preventing ImportNestedModule from ever getting called.\r\n\r\nI found the code that is not checking for a list type in the IronPython source file IronPython\\Runtime\\Importer.cs at around lines 151 and 120 as seen below\r\n```C#\r\nobject path;\r\nList listPath;\r\n    if (scope.__dict__._storage.TryGetPath(out path) && (listPath = path as List) != null) {\r\n        return ImportNestedModule(context, scope, new [] {name}, 0, listPath);\r\n                }\r\nIf you set __path__ to a string (in lieu of the expected list) the conversion to a list fails and ImportNestedModule is never called.\r\n```"}}