test_pkgutil.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. from pathlib import Path
  2. from test.support.import_helper import unload, CleanImport
  3. from test.support.warnings_helper import check_warnings
  4. import unittest
  5. import sys
  6. import importlib
  7. from importlib.util import spec_from_file_location
  8. import pkgutil
  9. import os
  10. import os.path
  11. import tempfile
  12. import shutil
  13. import zipfile
  14. # Note: pkgutil.walk_packages is currently tested in test_runpy. This is
  15. # a hack to get a major issue resolved for 3.3b2. Longer term, it should
  16. # be moved back here, perhaps by factoring out the helper code for
  17. # creating interesting package layouts to a separate module.
  18. # Issue #15348 declares this is indeed a dodgy hack ;)
  19. class PkgutilTests(unittest.TestCase):
  20. def setUp(self):
  21. self.dirname = tempfile.mkdtemp()
  22. self.addCleanup(shutil.rmtree, self.dirname)
  23. sys.path.insert(0, self.dirname)
  24. def tearDown(self):
  25. del sys.path[0]
  26. def test_getdata_filesys(self):
  27. pkg = 'test_getdata_filesys'
  28. # Include a LF and a CRLF, to test that binary data is read back
  29. RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
  30. # Make a package with some resources
  31. package_dir = os.path.join(self.dirname, pkg)
  32. os.mkdir(package_dir)
  33. # Empty init.py
  34. f = open(os.path.join(package_dir, '__init__.py'), "wb")
  35. f.close()
  36. # Resource files, res.txt, sub/res.txt
  37. f = open(os.path.join(package_dir, 'res.txt'), "wb")
  38. f.write(RESOURCE_DATA)
  39. f.close()
  40. os.mkdir(os.path.join(package_dir, 'sub'))
  41. f = open(os.path.join(package_dir, 'sub', 'res.txt'), "wb")
  42. f.write(RESOURCE_DATA)
  43. f.close()
  44. # Check we can read the resources
  45. res1 = pkgutil.get_data(pkg, 'res.txt')
  46. self.assertEqual(res1, RESOURCE_DATA)
  47. res2 = pkgutil.get_data(pkg, 'sub/res.txt')
  48. self.assertEqual(res2, RESOURCE_DATA)
  49. del sys.modules[pkg]
  50. def test_getdata_zipfile(self):
  51. zip = 'test_getdata_zipfile.zip'
  52. pkg = 'test_getdata_zipfile'
  53. # Include a LF and a CRLF, to test that binary data is read back
  54. RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
  55. # Make a package with some resources
  56. zip_file = os.path.join(self.dirname, zip)
  57. z = zipfile.ZipFile(zip_file, 'w')
  58. # Empty init.py
  59. z.writestr(pkg + '/__init__.py', "")
  60. # Resource files, res.txt, sub/res.txt
  61. z.writestr(pkg + '/res.txt', RESOURCE_DATA)
  62. z.writestr(pkg + '/sub/res.txt', RESOURCE_DATA)
  63. z.close()
  64. # Check we can read the resources
  65. sys.path.insert(0, zip_file)
  66. res1 = pkgutil.get_data(pkg, 'res.txt')
  67. self.assertEqual(res1, RESOURCE_DATA)
  68. res2 = pkgutil.get_data(pkg, 'sub/res.txt')
  69. self.assertEqual(res2, RESOURCE_DATA)
  70. names = []
  71. for moduleinfo in pkgutil.iter_modules([zip_file]):
  72. self.assertIsInstance(moduleinfo, pkgutil.ModuleInfo)
  73. names.append(moduleinfo.name)
  74. self.assertEqual(names, ['test_getdata_zipfile'])
  75. del sys.path[0]
  76. del sys.modules[pkg]
  77. def test_issue44061_iter_modules(self):
  78. #see: issue44061
  79. zip = 'test_getdata_zipfile.zip'
  80. pkg = 'test_getdata_zipfile'
  81. # Include a LF and a CRLF, to test that binary data is read back
  82. RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
  83. # Make a package with some resources
  84. zip_file = os.path.join(self.dirname, zip)
  85. z = zipfile.ZipFile(zip_file, 'w')
  86. # Empty init.py
  87. z.writestr(pkg + '/__init__.py', "")
  88. # Resource files, res.txt
  89. z.writestr(pkg + '/res.txt', RESOURCE_DATA)
  90. z.close()
  91. # Check we can read the resources
  92. sys.path.insert(0, zip_file)
  93. try:
  94. res = pkgutil.get_data(pkg, 'res.txt')
  95. self.assertEqual(res, RESOURCE_DATA)
  96. # make sure iter_modules accepts Path objects
  97. names = []
  98. for moduleinfo in pkgutil.iter_modules([Path(zip_file)]):
  99. self.assertIsInstance(moduleinfo, pkgutil.ModuleInfo)
  100. names.append(moduleinfo.name)
  101. self.assertEqual(names, [pkg])
  102. finally:
  103. del sys.path[0]
  104. sys.modules.pop(pkg, None)
  105. # assert path must be None or list of paths
  106. expected_msg = "path must be None or list of paths to look for modules in"
  107. with self.assertRaisesRegex(ValueError, expected_msg):
  108. list(pkgutil.iter_modules("invalid_path"))
  109. def test_unreadable_dir_on_syspath(self):
  110. # issue7367 - walk_packages failed if unreadable dir on sys.path
  111. package_name = "unreadable_package"
  112. d = os.path.join(self.dirname, package_name)
  113. # this does not appear to create an unreadable dir on Windows
  114. # but the test should not fail anyway
  115. os.mkdir(d, 0)
  116. self.addCleanup(os.rmdir, d)
  117. for t in pkgutil.walk_packages(path=[self.dirname]):
  118. self.fail("unexpected package found")
  119. def test_walkpackages_filesys(self):
  120. pkg1 = 'test_walkpackages_filesys'
  121. pkg1_dir = os.path.join(self.dirname, pkg1)
  122. os.mkdir(pkg1_dir)
  123. f = open(os.path.join(pkg1_dir, '__init__.py'), "wb")
  124. f.close()
  125. os.mkdir(os.path.join(pkg1_dir, 'sub'))
  126. f = open(os.path.join(pkg1_dir, 'sub', '__init__.py'), "wb")
  127. f.close()
  128. f = open(os.path.join(pkg1_dir, 'sub', 'mod.py'), "wb")
  129. f.close()
  130. # Now, to juice it up, let's add the opposite packages, too.
  131. pkg2 = 'sub'
  132. pkg2_dir = os.path.join(self.dirname, pkg2)
  133. os.mkdir(pkg2_dir)
  134. f = open(os.path.join(pkg2_dir, '__init__.py'), "wb")
  135. f.close()
  136. os.mkdir(os.path.join(pkg2_dir, 'test_walkpackages_filesys'))
  137. f = open(os.path.join(pkg2_dir, 'test_walkpackages_filesys', '__init__.py'), "wb")
  138. f.close()
  139. f = open(os.path.join(pkg2_dir, 'test_walkpackages_filesys', 'mod.py'), "wb")
  140. f.close()
  141. expected = [
  142. 'sub',
  143. 'sub.test_walkpackages_filesys',
  144. 'sub.test_walkpackages_filesys.mod',
  145. 'test_walkpackages_filesys',
  146. 'test_walkpackages_filesys.sub',
  147. 'test_walkpackages_filesys.sub.mod',
  148. ]
  149. actual= [e[1] for e in pkgutil.walk_packages([self.dirname])]
  150. self.assertEqual(actual, expected)
  151. for pkg in expected:
  152. if pkg.endswith('mod'):
  153. continue
  154. del sys.modules[pkg]
  155. def test_walkpackages_zipfile(self):
  156. """Tests the same as test_walkpackages_filesys, only with a zip file."""
  157. zip = 'test_walkpackages_zipfile.zip'
  158. pkg1 = 'test_walkpackages_zipfile'
  159. pkg2 = 'sub'
  160. zip_file = os.path.join(self.dirname, zip)
  161. z = zipfile.ZipFile(zip_file, 'w')
  162. z.writestr(pkg2 + '/__init__.py', "")
  163. z.writestr(pkg2 + '/' + pkg1 + '/__init__.py', "")
  164. z.writestr(pkg2 + '/' + pkg1 + '/mod.py', "")
  165. z.writestr(pkg1 + '/__init__.py', "")
  166. z.writestr(pkg1 + '/' + pkg2 + '/__init__.py', "")
  167. z.writestr(pkg1 + '/' + pkg2 + '/mod.py', "")
  168. z.close()
  169. sys.path.insert(0, zip_file)
  170. expected = [
  171. 'sub',
  172. 'sub.test_walkpackages_zipfile',
  173. 'sub.test_walkpackages_zipfile.mod',
  174. 'test_walkpackages_zipfile',
  175. 'test_walkpackages_zipfile.sub',
  176. 'test_walkpackages_zipfile.sub.mod',
  177. ]
  178. actual= [e[1] for e in pkgutil.walk_packages([zip_file])]
  179. self.assertEqual(actual, expected)
  180. del sys.path[0]
  181. for pkg in expected:
  182. if pkg.endswith('mod'):
  183. continue
  184. del sys.modules[pkg]
  185. def test_walk_packages_raises_on_string_or_bytes_input(self):
  186. str_input = 'test_dir'
  187. with self.assertRaises((TypeError, ValueError)):
  188. list(pkgutil.walk_packages(str_input))
  189. bytes_input = b'test_dir'
  190. with self.assertRaises((TypeError, ValueError)):
  191. list(pkgutil.walk_packages(bytes_input))
  192. def test_name_resolution(self):
  193. import logging
  194. import logging.handlers
  195. success_cases = (
  196. ('os', os),
  197. ('os.path', os.path),
  198. ('os.path:pathsep', os.path.pathsep),
  199. ('logging', logging),
  200. ('logging:', logging),
  201. ('logging.handlers', logging.handlers),
  202. ('logging.handlers:', logging.handlers),
  203. ('logging.handlers:SysLogHandler', logging.handlers.SysLogHandler),
  204. ('logging.handlers.SysLogHandler', logging.handlers.SysLogHandler),
  205. ('logging.handlers:SysLogHandler.LOG_ALERT',
  206. logging.handlers.SysLogHandler.LOG_ALERT),
  207. ('logging.handlers.SysLogHandler.LOG_ALERT',
  208. logging.handlers.SysLogHandler.LOG_ALERT),
  209. ('builtins.int', int),
  210. ('builtins:int', int),
  211. ('builtins.int.from_bytes', int.from_bytes),
  212. ('builtins:int.from_bytes', int.from_bytes),
  213. ('builtins.ZeroDivisionError', ZeroDivisionError),
  214. ('builtins:ZeroDivisionError', ZeroDivisionError),
  215. ('os:path', os.path),
  216. )
  217. failure_cases = (
  218. (None, TypeError),
  219. (1, TypeError),
  220. (2.0, TypeError),
  221. (True, TypeError),
  222. ('', ValueError),
  223. ('?abc', ValueError),
  224. ('abc/foo', ValueError),
  225. ('foo', ImportError),
  226. ('os.foo', AttributeError),
  227. ('os.foo:', ImportError),
  228. ('os.pth:pathsep', ImportError),
  229. ('logging.handlers:NoSuchHandler', AttributeError),
  230. ('logging.handlers:SysLogHandler.NO_SUCH_VALUE', AttributeError),
  231. ('logging.handlers.SysLogHandler.NO_SUCH_VALUE', AttributeError),
  232. ('ZeroDivisionError', ImportError),
  233. ('os.path.9abc', ValueError),
  234. ('9abc', ValueError),
  235. )
  236. # add some Unicode package names to the mix.
  237. unicode_words = ('\u0935\u092e\u0938',
  238. '\xe9', '\xc8',
  239. '\uc548\ub155\ud558\uc138\uc694',
  240. '\u3055\u3088\u306a\u3089',
  241. '\u3042\u308a\u304c\u3068\u3046',
  242. '\u0425\u043e\u0440\u043e\u0448\u043e',
  243. '\u0441\u043f\u0430\u0441\u0438\u0431\u043e',
  244. '\u73b0\u4ee3\u6c49\u8bed\u5e38\u7528\u5b57\u8868')
  245. for uw in unicode_words:
  246. d = os.path.join(self.dirname, uw)
  247. try:
  248. os.makedirs(d, exist_ok=True)
  249. except UnicodeEncodeError:
  250. # When filesystem encoding cannot encode uw: skip this test
  251. continue
  252. # make an empty __init__.py file
  253. f = os.path.join(d, '__init__.py')
  254. with open(f, 'w') as f:
  255. f.write('')
  256. f.flush()
  257. # now import the package we just created; clearing the caches is
  258. # needed, otherwise the newly created package isn't found
  259. importlib.invalidate_caches()
  260. mod = importlib.import_module(uw)
  261. success_cases += (uw, mod),
  262. if len(uw) > 1:
  263. failure_cases += (uw[:-1], ImportError),
  264. # add an example with a Unicode digit at the start
  265. failure_cases += ('\u0966\u0935\u092e\u0938', ValueError),
  266. for s, expected in success_cases:
  267. with self.subTest(s=s):
  268. o = pkgutil.resolve_name(s)
  269. self.assertEqual(o, expected)
  270. for s, exc in failure_cases:
  271. with self.subTest(s=s):
  272. with self.assertRaises(exc):
  273. pkgutil.resolve_name(s)
  274. class PkgutilPEP302Tests(unittest.TestCase):
  275. class MyTestLoader(object):
  276. def create_module(self, spec):
  277. return None
  278. def exec_module(self, mod):
  279. # Count how many times the module is reloaded
  280. mod.__dict__['loads'] = mod.__dict__.get('loads', 0) + 1
  281. def get_data(self, path):
  282. return "Hello, world!"
  283. class MyTestImporter(object):
  284. def find_spec(self, fullname, path=None, target=None):
  285. loader = PkgutilPEP302Tests.MyTestLoader()
  286. return spec_from_file_location(fullname,
  287. '<%s>' % loader.__class__.__name__,
  288. loader=loader,
  289. submodule_search_locations=[])
  290. def setUp(self):
  291. sys.meta_path.insert(0, self.MyTestImporter())
  292. def tearDown(self):
  293. del sys.meta_path[0]
  294. def test_getdata_pep302(self):
  295. # Use a dummy finder/loader
  296. self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
  297. del sys.modules['foo']
  298. def test_alreadyloaded(self):
  299. # Ensure that get_data works without reloading - the "loads" module
  300. # variable in the example loader should count how many times a reload
  301. # occurs.
  302. import foo
  303. self.assertEqual(foo.loads, 1)
  304. self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
  305. self.assertEqual(foo.loads, 1)
  306. del sys.modules['foo']
  307. # These tests, especially the setup and cleanup, are hideous. They
  308. # need to be cleaned up once issue 14715 is addressed.
  309. class ExtendPathTests(unittest.TestCase):
  310. def create_init(self, pkgname):
  311. dirname = tempfile.mkdtemp()
  312. sys.path.insert(0, dirname)
  313. pkgdir = os.path.join(dirname, pkgname)
  314. os.mkdir(pkgdir)
  315. with open(os.path.join(pkgdir, '__init__.py'), 'w') as fl:
  316. fl.write('from pkgutil import extend_path\n__path__ = extend_path(__path__, __name__)\n')
  317. return dirname
  318. def create_submodule(self, dirname, pkgname, submodule_name, value):
  319. module_name = os.path.join(dirname, pkgname, submodule_name + '.py')
  320. with open(module_name, 'w') as fl:
  321. print('value={}'.format(value), file=fl)
  322. def test_simple(self):
  323. pkgname = 'foo'
  324. dirname_0 = self.create_init(pkgname)
  325. dirname_1 = self.create_init(pkgname)
  326. self.create_submodule(dirname_0, pkgname, 'bar', 0)
  327. self.create_submodule(dirname_1, pkgname, 'baz', 1)
  328. import foo.bar
  329. import foo.baz
  330. # Ensure we read the expected values
  331. self.assertEqual(foo.bar.value, 0)
  332. self.assertEqual(foo.baz.value, 1)
  333. # Ensure the path is set up correctly
  334. self.assertEqual(sorted(foo.__path__),
  335. sorted([os.path.join(dirname_0, pkgname),
  336. os.path.join(dirname_1, pkgname)]))
  337. # Cleanup
  338. shutil.rmtree(dirname_0)
  339. shutil.rmtree(dirname_1)
  340. del sys.path[0]
  341. del sys.path[0]
  342. del sys.modules['foo']
  343. del sys.modules['foo.bar']
  344. del sys.modules['foo.baz']
  345. # Another awful testing hack to be cleaned up once the test_runpy
  346. # helpers are factored out to a common location
  347. def test_iter_importers(self):
  348. iter_importers = pkgutil.iter_importers
  349. get_importer = pkgutil.get_importer
  350. pkgname = 'spam'
  351. modname = 'eggs'
  352. dirname = self.create_init(pkgname)
  353. pathitem = os.path.join(dirname, pkgname)
  354. fullname = '{}.{}'.format(pkgname, modname)
  355. sys.modules.pop(fullname, None)
  356. sys.modules.pop(pkgname, None)
  357. try:
  358. self.create_submodule(dirname, pkgname, modname, 0)
  359. importlib.import_module(fullname)
  360. importers = list(iter_importers(fullname))
  361. expected_importer = get_importer(pathitem)
  362. for finder in importers:
  363. spec = pkgutil._get_spec(finder, fullname)
  364. loader = spec.loader
  365. try:
  366. loader = loader.loader
  367. except AttributeError:
  368. # For now we still allow raw loaders from
  369. # find_module().
  370. pass
  371. self.assertIsInstance(finder, importlib.machinery.FileFinder)
  372. self.assertEqual(finder, expected_importer)
  373. self.assertIsInstance(loader,
  374. importlib.machinery.SourceFileLoader)
  375. self.assertIsNone(pkgutil._get_spec(finder, pkgname))
  376. with self.assertRaises(ImportError):
  377. list(iter_importers('invalid.module'))
  378. with self.assertRaises(ImportError):
  379. list(iter_importers('.spam'))
  380. finally:
  381. shutil.rmtree(dirname)
  382. del sys.path[0]
  383. try:
  384. del sys.modules['spam']
  385. del sys.modules['spam.eggs']
  386. except KeyError:
  387. pass
  388. def test_mixed_namespace(self):
  389. pkgname = 'foo'
  390. dirname_0 = self.create_init(pkgname)
  391. dirname_1 = self.create_init(pkgname)
  392. self.create_submodule(dirname_0, pkgname, 'bar', 0)
  393. # Turn this into a PEP 420 namespace package
  394. os.unlink(os.path.join(dirname_0, pkgname, '__init__.py'))
  395. self.create_submodule(dirname_1, pkgname, 'baz', 1)
  396. import foo.bar
  397. import foo.baz
  398. # Ensure we read the expected values
  399. self.assertEqual(foo.bar.value, 0)
  400. self.assertEqual(foo.baz.value, 1)
  401. # Ensure the path is set up correctly
  402. self.assertEqual(sorted(foo.__path__),
  403. sorted([os.path.join(dirname_0, pkgname),
  404. os.path.join(dirname_1, pkgname)]))
  405. # Cleanup
  406. shutil.rmtree(dirname_0)
  407. shutil.rmtree(dirname_1)
  408. del sys.path[0]
  409. del sys.path[0]
  410. del sys.modules['foo']
  411. del sys.modules['foo.bar']
  412. del sys.modules['foo.baz']
  413. # XXX: test .pkg files
  414. class NestedNamespacePackageTest(unittest.TestCase):
  415. def setUp(self):
  416. self.basedir = tempfile.mkdtemp()
  417. self.old_path = sys.path[:]
  418. def tearDown(self):
  419. sys.path[:] = self.old_path
  420. shutil.rmtree(self.basedir)
  421. def create_module(self, name, contents):
  422. base, final = name.rsplit('.', 1)
  423. base_path = os.path.join(self.basedir, base.replace('.', os.path.sep))
  424. os.makedirs(base_path, exist_ok=True)
  425. with open(os.path.join(base_path, final + ".py"), 'w') as f:
  426. f.write(contents)
  427. def test_nested(self):
  428. pkgutil_boilerplate = (
  429. 'import pkgutil; '
  430. '__path__ = pkgutil.extend_path(__path__, __name__)')
  431. self.create_module('a.pkg.__init__', pkgutil_boilerplate)
  432. self.create_module('b.pkg.__init__', pkgutil_boilerplate)
  433. self.create_module('a.pkg.subpkg.__init__', pkgutil_boilerplate)
  434. self.create_module('b.pkg.subpkg.__init__', pkgutil_boilerplate)
  435. self.create_module('a.pkg.subpkg.c', 'c = 1')
  436. self.create_module('b.pkg.subpkg.d', 'd = 2')
  437. sys.path.insert(0, os.path.join(self.basedir, 'a'))
  438. sys.path.insert(0, os.path.join(self.basedir, 'b'))
  439. import pkg
  440. self.addCleanup(unload, 'pkg')
  441. self.assertEqual(len(pkg.__path__), 2)
  442. import pkg.subpkg
  443. self.addCleanup(unload, 'pkg.subpkg')
  444. self.assertEqual(len(pkg.subpkg.__path__), 2)
  445. from pkg.subpkg.c import c
  446. from pkg.subpkg.d import d
  447. self.assertEqual(c, 1)
  448. self.assertEqual(d, 2)
  449. class ImportlibMigrationTests(unittest.TestCase):
  450. # With full PEP 302 support in the standard import machinery, the
  451. # PEP 302 emulation in this module is in the process of being
  452. # deprecated in favour of importlib proper
  453. def check_deprecated(self):
  454. return check_warnings(
  455. ("This emulation is deprecated and slated for removal in "
  456. "Python 3.12; use 'importlib' instead",
  457. DeprecationWarning))
  458. def test_importer_deprecated(self):
  459. with self.check_deprecated():
  460. pkgutil.ImpImporter("")
  461. def test_loader_deprecated(self):
  462. with self.check_deprecated():
  463. pkgutil.ImpLoader("", "", "", "")
  464. def test_get_loader_avoids_emulation(self):
  465. with check_warnings() as w:
  466. self.assertIsNotNone(pkgutil.get_loader("sys"))
  467. self.assertIsNotNone(pkgutil.get_loader("os"))
  468. self.assertIsNotNone(pkgutil.get_loader("test.support"))
  469. self.assertEqual(len(w.warnings), 0)
  470. @unittest.skipIf(__name__ == '__main__', 'not compatible with __main__')
  471. def test_get_loader_handles_missing_loader_attribute(self):
  472. global __loader__
  473. this_loader = __loader__
  474. del __loader__
  475. try:
  476. with check_warnings() as w:
  477. self.assertIsNotNone(pkgutil.get_loader(__name__))
  478. self.assertEqual(len(w.warnings), 0)
  479. finally:
  480. __loader__ = this_loader
  481. def test_get_loader_handles_missing_spec_attribute(self):
  482. name = 'spam'
  483. mod = type(sys)(name)
  484. del mod.__spec__
  485. with CleanImport(name):
  486. sys.modules[name] = mod
  487. loader = pkgutil.get_loader(name)
  488. self.assertIsNone(loader)
  489. def test_get_loader_handles_spec_attribute_none(self):
  490. name = 'spam'
  491. mod = type(sys)(name)
  492. mod.__spec__ = None
  493. with CleanImport(name):
  494. sys.modules[name] = mod
  495. loader = pkgutil.get_loader(name)
  496. self.assertIsNone(loader)
  497. def test_get_loader_None_in_sys_modules(self):
  498. name = 'totally bogus'
  499. sys.modules[name] = None
  500. try:
  501. loader = pkgutil.get_loader(name)
  502. finally:
  503. del sys.modules[name]
  504. self.assertIsNone(loader)
  505. def test_find_loader_missing_module(self):
  506. name = 'totally bogus'
  507. loader = pkgutil.find_loader(name)
  508. self.assertIsNone(loader)
  509. def test_find_loader_avoids_emulation(self):
  510. with check_warnings() as w:
  511. self.assertIsNotNone(pkgutil.find_loader("sys"))
  512. self.assertIsNotNone(pkgutil.find_loader("os"))
  513. self.assertIsNotNone(pkgutil.find_loader("test.support"))
  514. self.assertEqual(len(w.warnings), 0)
  515. def test_get_importer_avoids_emulation(self):
  516. # We use an illegal path so *none* of the path hooks should fire
  517. with check_warnings() as w:
  518. self.assertIsNone(pkgutil.get_importer("*??"))
  519. self.assertEqual(len(w.warnings), 0)
  520. def test_issue44061(self):
  521. try:
  522. pkgutil.get_importer(Path("/home"))
  523. except AttributeError:
  524. self.fail("Unexpected AttributeError when calling get_importer")
  525. def test_iter_importers_avoids_emulation(self):
  526. with check_warnings() as w:
  527. for importer in pkgutil.iter_importers(): pass
  528. self.assertEqual(len(w.warnings), 0)
  529. def tearDownModule():
  530. # this is necessary if test is run repeated (like when finding leaks)
  531. import zipimport
  532. import importlib
  533. zipimport._zip_directory_cache.clear()
  534. importlib.invalidate_caches()
  535. if __name__ == '__main__':
  536. unittest.main()