test_pkg.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. # Test packages (dotted-name import)
  2. import sys
  3. import os
  4. import tempfile
  5. import textwrap
  6. import unittest
  7. # Helpers to create and destroy hierarchies.
  8. def cleanout(root):
  9. names = os.listdir(root)
  10. for name in names:
  11. fullname = os.path.join(root, name)
  12. if os.path.isdir(fullname) and not os.path.islink(fullname):
  13. cleanout(fullname)
  14. else:
  15. os.remove(fullname)
  16. os.rmdir(root)
  17. def fixdir(lst):
  18. if "__builtins__" in lst:
  19. lst.remove("__builtins__")
  20. if "__initializing__" in lst:
  21. lst.remove("__initializing__")
  22. return lst
  23. # XXX Things to test
  24. #
  25. # import package without __init__
  26. # import package with __init__
  27. # __init__ importing submodule
  28. # __init__ importing global module
  29. # __init__ defining variables
  30. # submodule importing other submodule
  31. # submodule importing global module
  32. # submodule import submodule via global name
  33. # from package import submodule
  34. # from package import subpackage
  35. # from package import variable (defined in __init__)
  36. # from package import * (defined in __init__)
  37. class TestPkg(unittest.TestCase):
  38. def setUp(self):
  39. self.root = None
  40. self.pkgname = None
  41. self.syspath = list(sys.path)
  42. self.modules_to_cleanup = set() # Populated by mkhier().
  43. def tearDown(self):
  44. sys.path[:] = self.syspath
  45. for modulename in self.modules_to_cleanup:
  46. if modulename in sys.modules:
  47. del sys.modules[modulename]
  48. if self.root: # Only clean if the test was actually run
  49. cleanout(self.root)
  50. # delete all modules concerning the tested hierarchy
  51. if self.pkgname:
  52. modules = [name for name in sys.modules
  53. if self.pkgname in name.split('.')]
  54. for name in modules:
  55. del sys.modules[name]
  56. def run_code(self, code):
  57. exec(textwrap.dedent(code), globals(), {"self": self})
  58. def mkhier(self, descr):
  59. root = tempfile.mkdtemp()
  60. sys.path.insert(0, root)
  61. if not os.path.isdir(root):
  62. os.mkdir(root)
  63. for name, contents in descr:
  64. comps = name.split()
  65. self.modules_to_cleanup.add('.'.join(comps))
  66. fullname = root
  67. for c in comps:
  68. fullname = os.path.join(fullname, c)
  69. if contents is None:
  70. os.mkdir(fullname)
  71. else:
  72. with open(fullname, "w") as f:
  73. f.write(contents)
  74. if not contents.endswith('\n'):
  75. f.write('\n')
  76. self.root = root
  77. # package name is the name of the first item
  78. self.pkgname = descr[0][0]
  79. def test_1(self):
  80. hier = [("t1", None), ("t1 __init__.py", "")]
  81. self.mkhier(hier)
  82. import t1
  83. def test_2(self):
  84. hier = [
  85. ("t2", None),
  86. ("t2 __init__.py", "'doc for t2'"),
  87. ("t2 sub", None),
  88. ("t2 sub __init__.py", ""),
  89. ("t2 sub subsub", None),
  90. ("t2 sub subsub __init__.py", "spam = 1"),
  91. ]
  92. self.mkhier(hier)
  93. import t2.sub
  94. import t2.sub.subsub
  95. self.assertEqual(t2.__name__, "t2")
  96. self.assertEqual(t2.sub.__name__, "t2.sub")
  97. self.assertEqual(t2.sub.subsub.__name__, "t2.sub.subsub")
  98. # This exec crap is needed because Py3k forbids 'import *' outside
  99. # of module-scope and __import__() is insufficient for what we need.
  100. s = """
  101. import t2
  102. from t2 import *
  103. self.assertEqual(dir(), ['self', 'sub', 't2'])
  104. """
  105. self.run_code(s)
  106. from t2 import sub
  107. from t2.sub import subsub
  108. from t2.sub.subsub import spam
  109. self.assertEqual(sub.__name__, "t2.sub")
  110. self.assertEqual(subsub.__name__, "t2.sub.subsub")
  111. self.assertEqual(sub.subsub.__name__, "t2.sub.subsub")
  112. for name in ['spam', 'sub', 'subsub', 't2']:
  113. self.assertTrue(locals()["name"], "Failed to import %s" % name)
  114. import t2.sub
  115. import t2.sub.subsub
  116. self.assertEqual(t2.__name__, "t2")
  117. self.assertEqual(t2.sub.__name__, "t2.sub")
  118. self.assertEqual(t2.sub.subsub.__name__, "t2.sub.subsub")
  119. s = """
  120. from t2 import *
  121. self.assertEqual(dir(), ['self', 'sub'])
  122. """
  123. self.run_code(s)
  124. def test_3(self):
  125. hier = [
  126. ("t3", None),
  127. ("t3 __init__.py", ""),
  128. ("t3 sub", None),
  129. ("t3 sub __init__.py", ""),
  130. ("t3 sub subsub", None),
  131. ("t3 sub subsub __init__.py", "spam = 1"),
  132. ]
  133. self.mkhier(hier)
  134. import t3.sub.subsub
  135. self.assertEqual(t3.__name__, "t3")
  136. self.assertEqual(t3.sub.__name__, "t3.sub")
  137. self.assertEqual(t3.sub.subsub.__name__, "t3.sub.subsub")
  138. def test_4(self):
  139. hier = [
  140. ("t4.py", "raise RuntimeError('Shouldnt load t4.py')"),
  141. ("t4", None),
  142. ("t4 __init__.py", ""),
  143. ("t4 sub.py", "raise RuntimeError('Shouldnt load sub.py')"),
  144. ("t4 sub", None),
  145. ("t4 sub __init__.py", ""),
  146. ("t4 sub subsub.py",
  147. "raise RuntimeError('Shouldnt load subsub.py')"),
  148. ("t4 sub subsub", None),
  149. ("t4 sub subsub __init__.py", "spam = 1"),
  150. ]
  151. self.mkhier(hier)
  152. s = """
  153. from t4.sub.subsub import *
  154. self.assertEqual(spam, 1)
  155. """
  156. self.run_code(s)
  157. def test_5(self):
  158. hier = [
  159. ("t5", None),
  160. ("t5 __init__.py", "import t5.foo"),
  161. ("t5 string.py", "spam = 1"),
  162. ("t5 foo.py",
  163. "from . import string; assert string.spam == 1"),
  164. ]
  165. self.mkhier(hier)
  166. import t5
  167. s = """
  168. from t5 import *
  169. self.assertEqual(dir(), ['foo', 'self', 'string', 't5'])
  170. """
  171. self.run_code(s)
  172. import t5
  173. self.assertEqual(fixdir(dir(t5)),
  174. ['__cached__', '__doc__', '__file__', '__loader__',
  175. '__name__', '__package__', '__path__', '__spec__',
  176. 'foo', 'string', 't5'])
  177. self.assertEqual(fixdir(dir(t5.foo)),
  178. ['__cached__', '__doc__', '__file__', '__loader__',
  179. '__name__', '__package__', '__spec__', 'string'])
  180. self.assertEqual(fixdir(dir(t5.string)),
  181. ['__cached__', '__doc__', '__file__', '__loader__',
  182. '__name__', '__package__', '__spec__', 'spam'])
  183. def test_6(self):
  184. hier = [
  185. ("t6", None),
  186. ("t6 __init__.py",
  187. "__all__ = ['spam', 'ham', 'eggs']"),
  188. ("t6 spam.py", ""),
  189. ("t6 ham.py", ""),
  190. ("t6 eggs.py", ""),
  191. ]
  192. self.mkhier(hier)
  193. import t6
  194. self.assertEqual(fixdir(dir(t6)),
  195. ['__all__', '__cached__', '__doc__', '__file__',
  196. '__loader__', '__name__', '__package__', '__path__',
  197. '__spec__'])
  198. s = """
  199. import t6
  200. from t6 import *
  201. self.assertEqual(fixdir(dir(t6)),
  202. ['__all__', '__cached__', '__doc__', '__file__',
  203. '__loader__', '__name__', '__package__',
  204. '__path__', '__spec__', 'eggs', 'ham', 'spam'])
  205. self.assertEqual(dir(), ['eggs', 'ham', 'self', 'spam', 't6'])
  206. """
  207. self.run_code(s)
  208. def test_7(self):
  209. hier = [
  210. ("t7.py", ""),
  211. ("t7", None),
  212. ("t7 __init__.py", ""),
  213. ("t7 sub.py",
  214. "raise RuntimeError('Shouldnt load sub.py')"),
  215. ("t7 sub", None),
  216. ("t7 sub __init__.py", ""),
  217. ("t7 sub .py",
  218. "raise RuntimeError('Shouldnt load subsub.py')"),
  219. ("t7 sub subsub", None),
  220. ("t7 sub subsub __init__.py",
  221. "spam = 1"),
  222. ]
  223. self.mkhier(hier)
  224. t7, sub, subsub = None, None, None
  225. import t7 as tas
  226. self.assertEqual(fixdir(dir(tas)),
  227. ['__cached__', '__doc__', '__file__', '__loader__',
  228. '__name__', '__package__', '__path__', '__spec__'])
  229. self.assertFalse(t7)
  230. from t7 import sub as subpar
  231. self.assertEqual(fixdir(dir(subpar)),
  232. ['__cached__', '__doc__', '__file__', '__loader__',
  233. '__name__', '__package__', '__path__', '__spec__'])
  234. self.assertFalse(t7)
  235. self.assertFalse(sub)
  236. from t7.sub import subsub as subsubsub
  237. self.assertEqual(fixdir(dir(subsubsub)),
  238. ['__cached__', '__doc__', '__file__', '__loader__',
  239. '__name__', '__package__', '__path__', '__spec__',
  240. 'spam'])
  241. self.assertFalse(t7)
  242. self.assertFalse(sub)
  243. self.assertFalse(subsub)
  244. from t7.sub.subsub import spam as ham
  245. self.assertEqual(ham, 1)
  246. self.assertFalse(t7)
  247. self.assertFalse(sub)
  248. self.assertFalse(subsub)
  249. @unittest.skipIf(sys.flags.optimize >= 2,
  250. "Docstrings are omitted with -O2 and above")
  251. def test_8(self):
  252. hier = [
  253. ("t8", None),
  254. ("t8 __init__"+os.extsep+"py", "'doc for t8'"),
  255. ]
  256. self.mkhier(hier)
  257. import t8
  258. self.assertEqual(t8.__doc__, "doc for t8")
  259. if __name__ == "__main__":
  260. unittest.main()