1# Tests command line execution of scripts
2
3import unittest
4import os
5import os.path
6import test.test_support
7from test.script_helper import (run_python,
8                                temp_dir, make_script, compile_script,
9                                make_pkg, make_zip_script, make_zip_pkg)
10
11verbose = test.test_support.verbose
12
13
14test_source = """\
15# Script may be run with optimisation enabled, so don't rely on assert
16# statements being executed
17def assertEqual(lhs, rhs):
18    if lhs != rhs:
19        raise AssertionError('%r != %r' % (lhs, rhs))
20def assertIdentical(lhs, rhs):
21    if lhs is not rhs:
22        raise AssertionError('%r is not %r' % (lhs, rhs))
23# Check basic code execution
24result = ['Top level assignment']
25def f():
26    result.append('Lower level reference')
27f()
28assertEqual(result, ['Top level assignment', 'Lower level reference'])
29# Check population of magic variables
30assertEqual(__name__, '__main__')
31print '__file__==%r' % __file__
32print '__package__==%r' % __package__
33# Check the sys module
34import sys
35assertIdentical(globals(), sys.modules[__name__].__dict__)
36print 'sys.argv[0]==%r' % sys.argv[0]
37"""
38
39def _make_test_script(script_dir, script_basename, source=test_source):
40    return make_script(script_dir, script_basename, source)
41
42def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
43                       source=test_source, depth=1):
44    return make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
45                        source, depth)
46
47# There's no easy way to pass the script directory in to get
48# -m to work (avoiding that is the whole point of making
49# directories and zipfiles executable!)
50# So we fake it for testing purposes with a custom launch script
51launch_source = """\
52import sys, os.path, runpy
53sys.path.insert(0, %s)
54runpy._run_module_as_main(%r)
55"""
56
57def _make_launch_script(script_dir, script_basename, module_name, path=None):
58    if path is None:
59        path = "os.path.dirname(__file__)"
60    else:
61        path = repr(path)
62    source = launch_source % (path, module_name)
63    return make_script(script_dir, script_basename, source)
64
65class CmdLineTest(unittest.TestCase):
66    def _check_script(self, script_name, expected_file,
67                            expected_argv0, expected_package,
68                            *cmd_line_switches):
69        run_args = cmd_line_switches + (script_name,)
70        exit_code, data = run_python(*run_args)
71        if verbose:
72            print 'Output from test script %r:' % script_name
73            print data
74        self.assertEqual(exit_code, 0)
75        printed_file = '__file__==%r' % expected_file
76        printed_argv0 = 'sys.argv[0]==%r' % expected_argv0
77        printed_package = '__package__==%r' % expected_package
78        if verbose:
79            print 'Expected output:'
80            print printed_file
81            print printed_package
82            print printed_argv0
83        self.assertIn(printed_file, data)
84        self.assertIn(printed_package, data)
85        self.assertIn(printed_argv0, data)
86
87    def _check_import_error(self, script_name, expected_msg,
88                            *cmd_line_switches):
89        run_args = cmd_line_switches + (script_name,)
90        exit_code, data = run_python(*run_args)
91        if verbose:
92            print 'Output from test script %r:' % script_name
93            print data
94            print 'Expected output: %r' % expected_msg
95        self.assertIn(expected_msg, data)
96
97    def test_basic_script(self):
98        with temp_dir() as script_dir:
99            script_name = _make_test_script(script_dir, 'script')
100            self._check_script(script_name, script_name, script_name, None)
101
102    def test_script_compiled(self):
103        with temp_dir() as script_dir:
104            script_name = _make_test_script(script_dir, 'script')
105            compiled_name = compile_script(script_name)
106            os.remove(script_name)
107            self._check_script(compiled_name, compiled_name, compiled_name, None)
108
109    def test_directory(self):
110        with temp_dir() as script_dir:
111            script_name = _make_test_script(script_dir, '__main__')
112            self._check_script(script_dir, script_name, script_dir, '')
113
114    def test_directory_compiled(self):
115        with temp_dir() as script_dir:
116            script_name = _make_test_script(script_dir, '__main__')
117            compiled_name = compile_script(script_name)
118            os.remove(script_name)
119            self._check_script(script_dir, compiled_name, script_dir, '')
120
121    def test_directory_error(self):
122        with temp_dir() as script_dir:
123            msg = "can't find '__main__' module in %r" % script_dir
124            self._check_import_error(script_dir, msg)
125
126    def test_zipfile(self):
127        with temp_dir() as script_dir:
128            script_name = _make_test_script(script_dir, '__main__')
129            zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
130            self._check_script(zip_name, run_name, zip_name, '')
131
132    def test_zipfile_compiled(self):
133        with temp_dir() as script_dir:
134            script_name = _make_test_script(script_dir, '__main__')
135            compiled_name = compile_script(script_name)
136            zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
137            self._check_script(zip_name, run_name, zip_name, '')
138
139    def test_zipfile_error(self):
140        with temp_dir() as script_dir:
141            script_name = _make_test_script(script_dir, 'not_main')
142            zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
143            msg = "can't find '__main__' module in %r" % zip_name
144            self._check_import_error(zip_name, msg)
145
146    def test_module_in_package(self):
147        with temp_dir() as script_dir:
148            pkg_dir = os.path.join(script_dir, 'test_pkg')
149            make_pkg(pkg_dir)
150            script_name = _make_test_script(pkg_dir, 'script')
151            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script')
152            self._check_script(launch_name, script_name, script_name, 'test_pkg')
153
154    def test_module_in_package_in_zipfile(self):
155        with temp_dir() as script_dir:
156            zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script')
157            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name)
158            self._check_script(launch_name, run_name, run_name, 'test_pkg')
159
160    def test_module_in_subpackage_in_zipfile(self):
161        with temp_dir() as script_dir:
162            zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2)
163            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name)
164            self._check_script(launch_name, run_name, run_name, 'test_pkg.test_pkg')
165
166    def test_package(self):
167        with temp_dir() as script_dir:
168            pkg_dir = os.path.join(script_dir, 'test_pkg')
169            make_pkg(pkg_dir)
170            script_name = _make_test_script(pkg_dir, '__main__')
171            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
172            self._check_script(launch_name, script_name,
173                               script_name, 'test_pkg')
174
175    def test_package_compiled(self):
176        with temp_dir() as script_dir:
177            pkg_dir = os.path.join(script_dir, 'test_pkg')
178            make_pkg(pkg_dir)
179            script_name = _make_test_script(pkg_dir, '__main__')
180            compiled_name = compile_script(script_name)
181            os.remove(script_name)
182            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
183            self._check_script(launch_name, compiled_name,
184                               compiled_name, 'test_pkg')
185
186    def test_package_error(self):
187        with temp_dir() as script_dir:
188            pkg_dir = os.path.join(script_dir, 'test_pkg')
189            make_pkg(pkg_dir)
190            msg = ("'test_pkg' is a package and cannot "
191                   "be directly executed")
192            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
193            self._check_import_error(launch_name, msg)
194
195    def test_package_recursion(self):
196        with temp_dir() as script_dir:
197            pkg_dir = os.path.join(script_dir, 'test_pkg')
198            make_pkg(pkg_dir)
199            main_dir = os.path.join(pkg_dir, '__main__')
200            make_pkg(main_dir)
201            msg = ("Cannot use package as __main__ module; "
202                   "'test_pkg' is a package and cannot "
203                   "be directly executed")
204            launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
205            self._check_import_error(launch_name, msg)
206
207
208def test_main():
209    test.test_support.run_unittest(CmdLineTest)
210    test.test_support.reap_children()
211
212if __name__ == '__main__':
213    test_main()
214