test_sdist.py 10.8 KB
Newer Older
1 2 3 4 5
"""Tests for distutils.command.sdist."""
import os
import unittest
import shutil
import zipfile
6
import tarfile
7 8 9 10 11 12 13 14

# zlib is not used here, but if it's not available
# the tests that use zipfile may fail
try:
    import zlib
except ImportError:
    zlib = None

15 16 17 18 19 20 21
try:
    import grp
    import pwd
    UID_GID_SUPPORT = True
except ImportError:
    UID_GID_SUPPORT = False

22
from os.path import join
23
import sys
24
import tempfile
25
import warnings
26

27
from test.support import check_warnings
28 29
from test.support import captured_stdout

30
from distutils.command.sdist import sdist
31
from distutils.command.sdist import show_formats
32 33
from distutils.core import Distribution
from distutils.tests.test_config import PyPIRCCommandTestCase
34
from distutils.errors import DistutilsExecError, DistutilsOptionError
35
from distutils.spawn import find_executable
36
from distutils.tests import support
37
from distutils.log import WARN
38
from distutils.archive_util import ARCHIVE_FORMATS
39 40 41 42 43 44 45 46

SETUP_PY = """
from distutils.core import setup
import somecode

setup(name='fake')
"""

47 48
MANIFEST = """\
README
49
inroot.txt
50
setup.py
51 52
data%(sep)sdata.dt
scripts%(sep)sscript.py
53 54
some%(sep)sfile.txt
some%(sep)sother_file.txt
55 56 57
somecode%(sep)s__init__.py
somecode%(sep)sdoc.dat
somecode%(sep)sdoc.txt
58 59
"""

60
class SDistTestCase(PyPIRCCommandTestCase):
61 62

    def setUp(self):
63 64
        # PyPIRCCommandTestCase creates a temp dir already
        # and put it in self.tmp_dir
65
        super(SDistTestCase, self).setUp()
66
        # setting up an environment
67
        self.old_path = os.getcwd()
68 69
        os.mkdir(join(self.tmp_dir, 'somecode'))
        os.mkdir(join(self.tmp_dir, 'dist'))
70 71 72 73
        # a package, and a README
        self.write_file((self.tmp_dir, 'README'), 'xxx')
        self.write_file((self.tmp_dir, 'somecode', '__init__.py'), '#')
        self.write_file((self.tmp_dir, 'setup.py'), SETUP_PY)
74
        os.chdir(self.tmp_dir)
75 76

    def tearDown(self):
77
        # back to normal
78
        os.chdir(self.old_path)
79
        super(SDistTestCase, self).tearDown()
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

    def get_cmd(self, metadata=None):
        """Returns a cmd"""
        if metadata is None:
            metadata = {'name': 'fake', 'version': '1.0',
                        'url': 'xxx', 'author': 'xxx',
                        'author_email': 'xxx'}
        dist = Distribution(metadata)
        dist.script_name = 'setup.py'
        dist.packages = ['somecode']
        dist.include_package_data = True
        cmd = sdist(dist)
        cmd.dist_dir = 'dist'
        def _warn(*args):
            pass
        cmd.warn = _warn
        return dist, cmd
97

98
    @unittest.skipUnless(zlib, "requires zlib")
99 100 101 102 103 104
    def test_prune_file_list(self):
        # this test creates a package with some vcs dirs in it
        # and launch sdist to make sure they get pruned
        # on all systems

        # creating VCS directories with some files in them
105
        os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
106
        self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx')
107

108
        os.mkdir(join(self.tmp_dir, 'somecode', '.hg'))
109
        self.write_file((self.tmp_dir, 'somecode', '.hg',
110 111
                         'ok'), 'xxx')

112
        os.mkdir(join(self.tmp_dir, 'somecode', '.git'))
113
        self.write_file((self.tmp_dir, 'somecode', '.git',
114 115 116
                         'ok'), 'xxx')

        # now building a sdist
117
        dist, cmd = self.get_cmd()
118 119 120 121

        # zip is available universally
        # (tar might not be installed under win32)
        cmd.formats = ['zip']
122 123

        cmd.ensure_finalized()
124 125 126
        cmd.run()

        # now let's check what we have
127
        dist_folder = join(self.tmp_dir, 'dist')
128 129 130 131 132 133 134 135 136 137 138 139
        files = os.listdir(dist_folder)
        self.assertEquals(files, ['fake-1.0.zip'])

        zip_file = zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip'))
        try:
            content = zip_file.namelist()
        finally:
            zip_file.close()

        # making sure everything has been pruned correctly
        self.assertEquals(len(content), 4)

140
    @unittest.skipUnless(zlib, "requires zlib")
141 142
    def test_make_distribution(self):

143 144 145 146
        # check if tar and gzip are installed
        if (find_executable('tar') is None or
            find_executable('gzip') is None):
            return
147 148

        # now building a sdist
149
        dist, cmd = self.get_cmd()
150 151 152

        # creating a gztar then a tar
        cmd.formats = ['gztar', 'tar']
153
        cmd.ensure_finalized()
154 155 156
        cmd.run()

        # making sure we have two files
157
        dist_folder = join(self.tmp_dir, 'dist')
158 159 160 161 162 163 164 165 166 167
        result = os.listdir(dist_folder)
        result.sort()
        self.assertEquals(result,
                          ['fake-1.0.tar', 'fake-1.0.tar.gz'] )

        os.remove(join(dist_folder, 'fake-1.0.tar'))
        os.remove(join(dist_folder, 'fake-1.0.tar.gz'))

        # now trying a tar then a gztar
        cmd.formats = ['tar', 'gztar']
168 169

        cmd.ensure_finalized()
170 171 172 173 174 175 176
        cmd.run()

        result = os.listdir(dist_folder)
        result.sort()
        self.assertEquals(result,
                ['fake-1.0.tar', 'fake-1.0.tar.gz'])

177
    @unittest.skipUnless(zlib, "requires zlib")
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    def test_add_defaults(self):

        # http://bugs.python.org/issue2279

        # add_default should also include
        # data_files and package_data
        dist, cmd = self.get_cmd()

        # filling data_files by pointing files
        # in package_data
        dist.package_data = {'': ['*.cfg', '*.dat'],
                             'somecode': ['*.txt']}
        self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
        self.write_file((self.tmp_dir, 'somecode', 'doc.dat'), '#')

        # adding some data in data_files
        data_dir = join(self.tmp_dir, 'data')
        os.mkdir(data_dir)
        self.write_file((data_dir, 'data.dt'), '#')
197 198
        some_dir = join(self.tmp_dir, 'some')
        os.mkdir(some_dir)
199
        self.write_file((self.tmp_dir, 'inroot.txt'), '#')
200 201 202
        self.write_file((some_dir, 'file.txt'), '#')
        self.write_file((some_dir, 'other_file.txt'), '#')

203 204 205
        dist.data_files = [('data', ['data/data.dt',
                                     'inroot.txt',
                                     'notexisting']),
206 207
                           'some/file.txt',
                           'some/other_file.txt']
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

        # adding a script
        script_dir = join(self.tmp_dir, 'scripts')
        os.mkdir(script_dir)
        self.write_file((script_dir, 'script.py'), '#')
        dist.scripts = [join('scripts', 'script.py')]

        cmd.formats = ['zip']
        cmd.use_defaults = True

        cmd.ensure_finalized()
        cmd.run()

        # now let's check what we have
        dist_folder = join(self.tmp_dir, 'dist')
        files = os.listdir(dist_folder)
        self.assertEquals(files, ['fake-1.0.zip'])

        zip_file = zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip'))
        try:
            content = zip_file.namelist()
        finally:
            zip_file.close()

        # making sure everything was added
233
        self.assertEquals(len(content), 11)
234 235 236

        # checking the MANIFEST
        manifest = open(join(self.tmp_dir, 'MANIFEST')).read()
237
        self.assertEquals(manifest, MANIFEST % {'sep': os.sep})
238

239
    @unittest.skipUnless(zlib, "requires zlib")
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    def test_metadata_check_option(self):
        # testing the `medata-check` option
        dist, cmd = self.get_cmd(metadata={})

        # this should raise some warnings !
        # with the `check` subcommand
        cmd.ensure_finalized()
        cmd.run()
        warnings = self.get_logs(WARN)
        self.assertEquals(len(warnings), 2)

        # trying with a complete set of metadata
        self.clear_logs()
        dist, cmd = self.get_cmd()
        cmd.ensure_finalized()
        cmd.metadata_check = 0
        cmd.run()
        warnings = self.get_logs(WARN)
        self.assertEquals(len(warnings), 0)

    def test_check_metadata_deprecated(self):
        # makes sure make_metadata is deprecated
        dist, cmd = self.get_cmd()
        with check_warnings() as w:
            warnings.simplefilter("always")
            cmd.check_metadata()
            self.assertEquals(len(w.warnings), 1)

268 269 270 271 272 273 274 275 276 277
    def test_show_formats(self):
        with captured_stdout() as stdout:
            show_formats()

        # the output should be a header line + one line per format
        num_formats = len(ARCHIVE_FORMATS.keys())
        output = [line for line in stdout.getvalue().split('\n')
                  if line.strip().startswith('--formats=')]
        self.assertEquals(len(output), num_formats)

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    def test_finalize_options(self):

        dist, cmd = self.get_cmd()
        cmd.finalize_options()

        # default options set by finalize
        self.assertEquals(cmd.manifest, 'MANIFEST')
        self.assertEquals(cmd.template, 'MANIFEST.in')
        self.assertEquals(cmd.dist_dir, 'dist')

        # formats has to be a string splitable on (' ', ',') or
        # a stringlist
        cmd.formats = 1
        self.assertRaises(DistutilsOptionError, cmd.finalize_options)
        cmd.formats = ['zip']
        cmd.finalize_options()

        # formats has to be known
        cmd.formats = 'supazipa'
        self.assertRaises(DistutilsOptionError, cmd.finalize_options)

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    @unittest.skipUnless(zlib, "requires zlib")
    @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
    def test_make_distribution_owner_group(self):

        # check if tar and gzip are installed
        if (find_executable('tar') is None or
            find_executable('gzip') is None):
            return

        # now building a sdist
        dist, cmd = self.get_cmd()

        # creating a gztar and specifying the owner+group
        cmd.formats = ['gztar']
        cmd.owner = pwd.getpwuid(0)[0]
        cmd.group = grp.getgrgid(0)[0]
        cmd.ensure_finalized()
        cmd.run()

        # making sure we have the good rights
        archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
        archive = tarfile.open(archive_name)
        try:
            for member in archive.getmembers():
                self.assertEquals(member.uid, 0)
                self.assertEquals(member.gid, 0)
        finally:
            archive.close()

        # building a sdist again
        dist, cmd = self.get_cmd()

        # creating a gztar
        cmd.formats = ['gztar']
        cmd.ensure_finalized()
        cmd.run()

        # making sure we have the good rights
        archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
        archive = tarfile.open(archive_name)
339 340 341 342

        # note that we are not testing the group ownership here
        # because, depending on the platforms and the container
        # rights (see #7408)
343 344 345 346 347
        try:
            for member in archive.getmembers():
                self.assertEquals(member.uid, os.getuid())
        finally:
            archive.close()
348

349
def test_suite():
350
    return unittest.makeSuite(SDistTestCase)
351 352 353

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