1"""Tests for distutils.core."""
2
3import io
4import distutils.core
5import os
6import shutil
7import sys
8import test.support
9from test.support import captured_stdout, run_unittest
10import unittest
11from distutils.tests import support
12from distutils import log
13
14# setup script that uses __file__
15setup_using___file__ = """\
16
17__file__
18
19from distutils.core import setup
20setup()
21"""
22
23setup_prints_cwd = """\
24
25import os
26print(os.getcwd())
27
28from distutils.core import setup
29setup()
30"""
31
32setup_does_nothing = """\
33from distutils.core import setup
34setup()
35"""
36
37
38setup_defines_subclass = """\
39from distutils.core import setup
40from distutils.command.install import install as _install
41
42class install(_install):
43    sub_commands = _install.sub_commands + ['cmd']
44
45setup(cmdclass={'install': install})
46"""
47
48class CoreTestCase(support.EnvironGuard, unittest.TestCase):
49
50    def setUp(self):
51        super(CoreTestCase, self).setUp()
52        self.old_stdout = sys.stdout
53        self.cleanup_testfn()
54        self.old_argv = sys.argv, sys.argv[:]
55        self.addCleanup(log.set_threshold, log._global_log.threshold)
56
57    def tearDown(self):
58        sys.stdout = self.old_stdout
59        self.cleanup_testfn()
60        sys.argv = self.old_argv[0]
61        sys.argv[:] = self.old_argv[1]
62        super(CoreTestCase, self).tearDown()
63
64    def cleanup_testfn(self):
65        path = test.support.TESTFN
66        if os.path.isfile(path):
67            os.remove(path)
68        elif os.path.isdir(path):
69            shutil.rmtree(path)
70
71    def write_setup(self, text, path=test.support.TESTFN):
72        f = open(path, "w")
73        try:
74            f.write(text)
75        finally:
76            f.close()
77        return path
78
79    def test_run_setup_provides_file(self):
80        # Make sure the script can use __file__; if that's missing, the test
81        # setup.py script will raise NameError.
82        distutils.core.run_setup(
83            self.write_setup(setup_using___file__))
84
85    def test_run_setup_preserves_sys_argv(self):
86        # Make sure run_setup does not clobber sys.argv
87        argv_copy = sys.argv.copy()
88        distutils.core.run_setup(
89            self.write_setup(setup_does_nothing))
90        self.assertEqual(sys.argv, argv_copy)
91
92    def test_run_setup_defines_subclass(self):
93        # Make sure the script can use __file__; if that's missing, the test
94        # setup.py script will raise NameError.
95        dist = distutils.core.run_setup(
96            self.write_setup(setup_defines_subclass))
97        install = dist.get_command_obj('install')
98        self.assertIn('cmd', install.sub_commands)
99
100    def test_run_setup_uses_current_dir(self):
101        # This tests that the setup script is run with the current directory
102        # as its own current directory; this was temporarily broken by a
103        # previous patch when TESTFN did not use the current directory.
104        sys.stdout = io.StringIO()
105        cwd = os.getcwd()
106
107        # Create a directory and write the setup.py file there:
108        os.mkdir(test.support.TESTFN)
109        setup_py = os.path.join(test.support.TESTFN, "setup.py")
110        distutils.core.run_setup(
111            self.write_setup(setup_prints_cwd, path=setup_py))
112
113        output = sys.stdout.getvalue()
114        if output.endswith("\n"):
115            output = output[:-1]
116        self.assertEqual(cwd, output)
117
118    def test_debug_mode(self):
119        # this covers the code called when DEBUG is set
120        sys.argv = ['setup.py', '--name']
121        with captured_stdout() as stdout:
122            distutils.core.setup(name='bar')
123        stdout.seek(0)
124        self.assertEqual(stdout.read(), 'bar\n')
125
126        distutils.core.DEBUG = True
127        try:
128            with captured_stdout() as stdout:
129                distutils.core.setup(name='bar')
130        finally:
131            distutils.core.DEBUG = False
132        stdout.seek(0)
133        wanted = "options (after parsing config files):\n"
134        self.assertEqual(stdout.readlines()[0], wanted)
135
136def test_suite():
137    return unittest.makeSuite(CoreTestCase)
138
139if __name__ == "__main__":
140    run_unittest(test_suite())
141