test_modulefinder.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import __future__
  2. import os
  3. import unittest
  4. import distutils.dir_util
  5. import tempfile
  6. from test import test_support
  7. try: set
  8. except NameError: from sets import Set as set
  9. import modulefinder
  10. # Note: To test modulefinder with Python 2.2, sets.py and
  11. # modulefinder.py must be available - they are not in the standard
  12. # library.
  13. TEST_DIR = tempfile.mkdtemp()
  14. TEST_PATH = [TEST_DIR, os.path.dirname(__future__.__file__)]
  15. # Each test description is a list of 5 items:
  16. #
  17. # 1. a module name that will be imported by modulefinder
  18. # 2. a list of module names that modulefinder is required to find
  19. # 3. a list of module names that modulefinder should complain
  20. # about because they are not found
  21. # 4. a list of module names that modulefinder should complain
  22. # about because they MAY be not found
  23. # 5. a string specifying packages to create; the format is obvious imo.
  24. #
  25. # Each package will be created in TEST_DIR, and TEST_DIR will be
  26. # removed after the tests again.
  27. # Modulefinder searches in a path that contains TEST_DIR, plus
  28. # the standard Lib directory.
  29. maybe_test = [
  30. "a.module",
  31. ["a", "a.module", "sys",
  32. "b"],
  33. ["c"], ["b.something"],
  34. """\
  35. a/__init__.py
  36. a/module.py
  37. from b import something
  38. from c import something
  39. b/__init__.py
  40. from sys import *
  41. """]
  42. maybe_test_new = [
  43. "a.module",
  44. ["a", "a.module", "sys",
  45. "b", "__future__"],
  46. ["c"], ["b.something"],
  47. """\
  48. a/__init__.py
  49. a/module.py
  50. from b import something
  51. from c import something
  52. b/__init__.py
  53. from __future__ import absolute_import
  54. from sys import *
  55. """]
  56. package_test = [
  57. "a.module",
  58. ["a", "a.b", "a.c", "a.module", "mymodule", "sys"],
  59. ["blahblah"], [],
  60. """\
  61. mymodule.py
  62. a/__init__.py
  63. import blahblah
  64. from a import b
  65. import c
  66. a/module.py
  67. import sys
  68. from a import b as x
  69. from a.c import sillyname
  70. a/b.py
  71. a/c.py
  72. from a.module import x
  73. import mymodule as sillyname
  74. from sys import version_info
  75. """]
  76. absolute_import_test = [
  77. "a.module",
  78. ["a", "a.module",
  79. "b", "b.x", "b.y", "b.z",
  80. "__future__", "sys", "exceptions"],
  81. ["blahblah"], [],
  82. """\
  83. mymodule.py
  84. a/__init__.py
  85. a/module.py
  86. from __future__ import absolute_import
  87. import sys # sys
  88. import blahblah # fails
  89. import exceptions # exceptions
  90. import b.x # b.x
  91. from b import y # b.y
  92. from b.z import * # b.z.*
  93. a/exceptions.py
  94. a/sys.py
  95. import mymodule
  96. a/b/__init__.py
  97. a/b/x.py
  98. a/b/y.py
  99. a/b/z.py
  100. b/__init__.py
  101. import z
  102. b/unused.py
  103. b/x.py
  104. b/y.py
  105. b/z.py
  106. """]
  107. relative_import_test = [
  108. "a.module",
  109. ["__future__",
  110. "a", "a.module",
  111. "a.b", "a.b.y", "a.b.z",
  112. "a.b.c", "a.b.c.moduleC",
  113. "a.b.c.d", "a.b.c.e",
  114. "a.b.x",
  115. "exceptions"],
  116. [], [],
  117. """\
  118. mymodule.py
  119. a/__init__.py
  120. from .b import y, z # a.b.y, a.b.z
  121. a/module.py
  122. from __future__ import absolute_import # __future__
  123. import exceptions # exceptions
  124. a/exceptions.py
  125. a/sys.py
  126. a/b/__init__.py
  127. from ..b import x # a.b.x
  128. #from a.b.c import moduleC
  129. from .c import moduleC # a.b.moduleC
  130. a/b/x.py
  131. a/b/y.py
  132. a/b/z.py
  133. a/b/g.py
  134. a/b/c/__init__.py
  135. from ..c import e # a.b.c.e
  136. a/b/c/moduleC.py
  137. from ..c import d # a.b.c.d
  138. a/b/c/d.py
  139. a/b/c/e.py
  140. a/b/c/x.py
  141. """]
  142. relative_import_test_2 = [
  143. "a.module",
  144. ["a", "a.module",
  145. "a.sys",
  146. "a.b", "a.b.y", "a.b.z",
  147. "a.b.c", "a.b.c.d",
  148. "a.b.c.e",
  149. "a.b.c.moduleC",
  150. "a.b.c.f",
  151. "a.b.x",
  152. "a.another"],
  153. [], [],
  154. """\
  155. mymodule.py
  156. a/__init__.py
  157. from . import sys # a.sys
  158. a/another.py
  159. a/module.py
  160. from .b import y, z # a.b.y, a.b.z
  161. a/exceptions.py
  162. a/sys.py
  163. a/b/__init__.py
  164. from .c import moduleC # a.b.c.moduleC
  165. from .c import d # a.b.c.d
  166. a/b/x.py
  167. a/b/y.py
  168. a/b/z.py
  169. a/b/c/__init__.py
  170. from . import e # a.b.c.e
  171. a/b/c/moduleC.py
  172. #
  173. from . import f # a.b.c.f
  174. from .. import x # a.b.x
  175. from ... import another # a.another
  176. a/b/c/d.py
  177. a/b/c/e.py
  178. a/b/c/f.py
  179. """]
  180. relative_import_test_3 = [
  181. "a.module",
  182. ["a", "a.module"],
  183. ["a.bar"],
  184. [],
  185. """\
  186. a/__init__.py
  187. def foo(): pass
  188. a/module.py
  189. from . import foo
  190. from . import bar
  191. """]
  192. def open_file(path):
  193. ##print "#", os.path.abspath(path)
  194. dirname = os.path.dirname(path)
  195. distutils.dir_util.mkpath(dirname)
  196. return open(path, "w")
  197. def create_package(source):
  198. ofi = None
  199. try:
  200. for line in source.splitlines():
  201. if line.startswith(" ") or line.startswith("\t"):
  202. ofi.write(line.strip() + "\n")
  203. else:
  204. if ofi:
  205. ofi.close()
  206. ofi = open_file(os.path.join(TEST_DIR, line.strip()))
  207. finally:
  208. if ofi:
  209. ofi.close()
  210. class ModuleFinderTest(unittest.TestCase):
  211. def _do_test(self, info, report=False):
  212. import_this, modules, missing, maybe_missing, source = info
  213. create_package(source)
  214. try:
  215. mf = modulefinder.ModuleFinder(path=TEST_PATH)
  216. mf.import_hook(import_this)
  217. if report:
  218. mf.report()
  219. ## # This wouldn't work in general when executed several times:
  220. ## opath = sys.path[:]
  221. ## sys.path = TEST_PATH
  222. ## try:
  223. ## __import__(import_this)
  224. ## except:
  225. ## import traceback; traceback.print_exc()
  226. ## sys.path = opath
  227. ## return
  228. modules = set(modules)
  229. found = set(mf.modules.keys())
  230. more = list(found - modules)
  231. less = list(modules - found)
  232. # check if we found what we expected, not more, not less
  233. self.assertEqual((more, less), ([], []))
  234. # check for missing and maybe missing modules
  235. bad, maybe = mf.any_missing_maybe()
  236. self.assertEqual(bad, missing)
  237. self.assertEqual(maybe, maybe_missing)
  238. finally:
  239. distutils.dir_util.remove_tree(TEST_DIR)
  240. def test_package(self):
  241. self._do_test(package_test)
  242. def test_maybe(self):
  243. self._do_test(maybe_test)
  244. if getattr(__future__, "absolute_import", None):
  245. def test_maybe_new(self):
  246. self._do_test(maybe_test_new)
  247. def test_absolute_imports(self):
  248. self._do_test(absolute_import_test)
  249. def test_relative_imports(self):
  250. self._do_test(relative_import_test)
  251. def test_relative_imports_2(self):
  252. self._do_test(relative_import_test_2)
  253. def test_relative_imports_3(self):
  254. self._do_test(relative_import_test_3)
  255. def test_extended_opargs(self):
  256. extended_opargs_test = [
  257. "a",
  258. ["a", "b"],
  259. [], [],
  260. """\
  261. a.py
  262. %r
  263. import b
  264. b.py
  265. """ % range(2**16)] # 2**16 constants
  266. self._do_test(extended_opargs_test)
  267. def test_main():
  268. distutils.log.set_threshold(distutils.log.WARN)
  269. test_support.run_unittest(ModuleFinderTest)
  270. if __name__ == "__main__":
  271. unittest.main()