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