Fixing broken while loop in imports.py

Issue: flake8 occasionally encounters "H302  import only modules."
error even though the python module exists at the path and python
shell is able to import the same.

Root-cause: The while loop in is_module_for_sure() had a bug, where
iterating variable, 'mod_name', was getting derived from the same
input, 'mod', every time. It should have led to an infinite loop
otherwise. But, an ImportError takes it out of the loop. Most of
the cases, this is not an issue, if as part of the exception handler,
built-in __import__() finds the module. The evidence of the issue is
the availability of import statements suffixed with "# noqa" to
work-around the bug.

Fixing the while loop causes the logic to flow in the original path of
the code to use 'imp.find_module()'

Change-Id: I83d80b1cf6961568e825d4387443b285e490fb40
This commit is contained in:
Surojit Pathak 2014-11-21 22:51:58 +00:00
parent f0369f6b0d
commit 64ef5bf59d
2 changed files with 25 additions and 1 deletions

View File

@ -72,7 +72,7 @@ def hacking_import_rules(logical_line, physical_line, filename, noqa):
try:
mod_name = mod
while '.' in mod_name:
pack_name, _sep, mod_name = mod.partition('.')
pack_name, _sep, mod_name = mod_name.partition('.')
f, p, d = imp.find_module(pack_name, search_path)
search_path = [p]
imp.find_module(mod_name, search_path)

View File

@ -15,6 +15,7 @@
import mock
import six
import sys
from hacking.checks import imports
from hacking import tests
@ -29,6 +30,9 @@ def fake_find_module(module, path):
return (None, './oslo', None)
elif module == 'db' and path[0] == './oslo':
return (None, './oslo/db', None)
elif module == 'abc' and path[0] == './oslo/db':
# Let's fake, there is no abc.py at ./oslo/db/
raise ImportError
elif './oslo/db' in path[0] and module != '_':
return (None, '%s/%s' % (path[0], module), None)
raise ImportError
@ -55,3 +59,23 @@ class ImportTestCase(tests.TestCase):
mock_import.side_effect = ImportError
mod_name = 'oslo.db.openstack.common.gettextutils._'
self.assertEqual('project', imports._get_import_type(mod_name))
@mock.patch.object(sys, 'path', ['.'])
@mock.patch(import_name)
@mock.patch('imp.find_module')
def test_module_import(self, find_module, mock_import):
find_module.side_effect = fake_find_module
# API under test
aut = imports.hacking_import_rules
for num, msg in aut('from oslo.db import xyz', None, 'fake_file.py',
0):
# xyz should be found and this generator should be empty
self.fail('Module xyz should have been found under oslo.db')
for num, msg in aut('from oslo.db import abc', None, 'fake_file.py',
0):
# abc should not be found and we should get H302
self.assertTrue(msg.startswith('H302'))
for num, msg in aut('from oslo.db.myz import *', None, 'fake_file.py',
0):
# wildcard import is not allowed as per H303
self.assertTrue(msg.startswith('H303'))