summaryrefslogtreecommitdiffstats
path: root/Lib/packaging/tests/test_uninstall.py
blob: 2168b6fdf73dedf7d2b8229b955d0e1963139955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""Tests for the packaging.uninstall module."""
import os
import sys
import logging
import packaging.util

from packaging.errors import PackagingError
from packaging.install import remove
from packaging.database import disable_cache, enable_cache

from packaging.tests import unittest, support

SETUP_CFG = """
[metadata]
name = %(name)s
version = %(version)s

[files]
packages =
    %(pkg)s
    %(pkg)s.sub
"""


class UninstallTestCase(support.TempdirManager,
                        support.LoggingCatcher,
                        support.EnvironRestorer,
                        unittest.TestCase):

    restore_environ = ['PLAT']

    def setUp(self):
        super(UninstallTestCase, self).setUp()
        self.addCleanup(setattr, sys, 'stdout', sys.stdout)
        self.addCleanup(setattr, sys, 'stderr', sys.stderr)
        self.addCleanup(os.chdir, os.getcwd())
        self.addCleanup(enable_cache)
        self.root_dir = self.mkdtemp()
        self.cwd = os.getcwd()
        disable_cache()

    def tearDown(self):
        os.chdir(self.cwd)
        packaging.util._path_created.clear()
        super(UninstallTestCase, self).tearDown()

    def get_path(self, dist, name):
        # the dist argument must contain an install_dist command correctly
        # initialized with a prefix option and finalized befored this method
        # can be called successfully; practically, this means that you should
        # call self.install_dist before self.get_path
        cmd = dist.get_command_obj('install_dist')
        return getattr(cmd, 'install_' + name)

    def make_dist(self, name='Foo', **kw):
        kw['name'] = name
        pkg = name.lower()
        if 'version' not in kw:
            kw['version'] = '0.1'
        project_dir, dist = self.create_dist(**kw)
        kw['pkg'] = pkg

        pkg_dir = os.path.join(project_dir, pkg)
        os.makedirs(os.path.join(pkg_dir, 'sub'))

        self.write_file((project_dir, 'setup.cfg'), SETUP_CFG % kw)
        self.write_file((pkg_dir, '__init__.py'), '#')
        self.write_file((pkg_dir, pkg + '_utils.py'), '#')
        self.write_file((pkg_dir, 'sub', '__init__.py'), '#')
        self.write_file((pkg_dir, 'sub', pkg + '_utils.py'), '#')

        return project_dir

    def install_dist(self, name='Foo', dirname=None, **kw):
        if not dirname:
            dirname = self.make_dist(name, **kw)
        os.chdir(dirname)

        dist = support.TestDistribution()
        # for some unfathomable reason, the tests will fail horribly if the
        # parse_config_files method is not called, even if it doesn't do
        # anything useful; trying to build and use a command object manually
        # also fails
        dist.parse_config_files()
        dist.finalize_options()
        dist.run_command('install_dist',
                         {'prefix': ('command line', self.root_dir)})

        site_packages = self.get_path(dist, 'purelib')
        return dist, site_packages

    def test_uninstall_unknown_distribution(self):
        dist, site_packages = self.install_dist('Foospam')
        self.assertRaises(PackagingError, remove, 'Foo',
                          paths=[site_packages])

    def test_uninstall(self):
        dist, site_packages = self.install_dist()
        self.assertIsFile(site_packages, 'foo', '__init__.py')
        self.assertIsFile(site_packages, 'foo', 'sub', '__init__.py')
        self.assertIsFile(site_packages, 'Foo-0.1.dist-info', 'RECORD')
        self.assertTrue(remove('Foo', paths=[site_packages]))
        self.assertIsNotFile(site_packages, 'foo', 'sub', '__init__.py')
        self.assertIsNotFile(site_packages, 'Foo-0.1.dist-info', 'RECORD')

    def test_uninstall_error_handling(self):
        # makes sure if there are OSErrors (like permission denied)
        # remove() stops and displays a clean error
        dist, site_packages = self.install_dist('Meh')

        # breaking os.rename
        old = os.rename

        def _rename(source, target):
            raise OSError(42, 'impossible operation')

        os.rename = _rename
        try:
            self.assertFalse(remove('Meh', paths=[site_packages]))
        finally:
            os.rename = old

        logs = [log for log in self.get_logs(logging.INFO)
                if log.startswith('Error:')]
        self.assertEqual(logs, ['Error: [Errno 42] impossible operation'])

        self.assertTrue(remove('Meh', paths=[site_packages]))


def test_suite():
    return unittest.makeSuite(UninstallTestCase)

if __name__ == '__main__':
    unittest.main(defaultTest='test_suite')