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