~sakuag333/mailman/lmtp-duplicate-id

« back to all changes in this revision

Viewing changes to distribute_setup.py

  • Committer: Barry Warsaw
  • Date: 2012-12-15 18:00:29 UTC
  • Revision ID: barry@list.org-20121215180029-r5oc41ab4nc1m722
Update to the latest version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
This file can also be run as a script to install or upgrade setuptools.
15
15
"""
16
16
import os
 
17
import shutil
17
18
import sys
18
19
import time
19
20
import fnmatch
20
21
import tempfile
21
22
import tarfile
 
23
import optparse
 
24
 
22
25
from distutils import log
23
26
 
24
27
try:
46
49
            args = [quote(arg) for arg in args]
47
50
        return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
48
51
 
49
 
DEFAULT_VERSION = "0.6.8"
 
52
DEFAULT_VERSION = "0.6.32"
50
53
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
 
54
SETUPTOOLS_FAKED_VERSION = "0.6c11"
 
55
 
51
56
SETUPTOOLS_PKG_INFO = """\
52
57
Metadata-Version: 1.0
53
58
Name: setuptools
54
 
Version: 0.6c9
 
59
Version: %s
55
60
Summary: xxxx
56
61
Home-page: xxx
57
62
Author: xxx
58
63
Author-email: xxx
59
64
License: xxx
60
65
Description: xxx
61
 
"""
62
 
 
63
 
 
64
 
def _install(tarball):
 
66
""" % SETUPTOOLS_FAKED_VERSION
 
67
 
 
68
 
 
69
def _install(tarball, install_args=()):
65
70
    # extracting the tarball
66
71
    tmpdir = tempfile.mkdtemp()
67
72
    log.warn('Extracting in %s', tmpdir)
79
84
 
80
85
        # installing
81
86
        log.warn('Installing Distribute')
82
 
        assert _python_cmd('setup.py', 'install')
 
87
        if not _python_cmd('setup.py', 'install', *install_args):
 
88
            log.warn('Something went wrong during the installation.')
 
89
            log.warn('See the error message above.')
 
90
            # exitcode will be 2
 
91
            return 2
83
92
    finally:
84
93
        os.chdir(old_wd)
 
94
        shutil.rmtree(tmpdir)
85
95
 
86
96
 
87
97
def _build_egg(egg, tarball, to_dir):
106
116
 
107
117
    finally:
108
118
        os.chdir(old_wd)
 
119
        shutil.rmtree(tmpdir)
109
120
    # returning the result
110
121
    log.warn(egg)
111
122
    if not os.path.exists(egg):
140
151
        except ImportError:
141
152
            return _do_download(version, download_base, to_dir, download_delay)
142
153
        try:
143
 
            pkg_resources.require("distribute>="+version)
 
154
            pkg_resources.require("distribute>=" + version)
144
155
            return
145
156
        except pkg_resources.VersionConflict:
146
157
            e = sys.exc_info()[1]
163
174
        if not no_fake:
164
175
            _create_fake_setuptools_pkg_info(to_dir)
165
176
 
 
177
 
166
178
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
167
179
                        to_dir=os.curdir, delay=15):
168
180
    """Download distribute from a specified location and return its filename
200
212
    return os.path.realpath(saveto)
201
213
 
202
214
 
 
215
def _no_sandbox(function):
 
216
    def __no_sandbox(*args, **kw):
 
217
        try:
 
218
            from setuptools.sandbox import DirectorySandbox
 
219
            if not hasattr(DirectorySandbox, '_old'):
 
220
                def violation(*args):
 
221
                    pass
 
222
                DirectorySandbox._old = DirectorySandbox._violation
 
223
                DirectorySandbox._violation = violation
 
224
                patched = True
 
225
            else:
 
226
                patched = False
 
227
        except ImportError:
 
228
            patched = False
 
229
 
 
230
        try:
 
231
            return function(*args, **kw)
 
232
        finally:
 
233
            if patched:
 
234
                DirectorySandbox._violation = DirectorySandbox._old
 
235
                del DirectorySandbox._old
 
236
 
 
237
    return __no_sandbox
 
238
 
 
239
 
203
240
def _patch_file(path, content):
204
241
    """Will backup the file then patch it"""
205
242
    existing_content = open(path).read()
216
253
        f.close()
217
254
    return True
218
255
 
 
256
_patch_file = _no_sandbox(_patch_file)
 
257
 
219
258
 
220
259
def _same_content(path, content):
221
260
    return open(path).read() == content
223
262
 
224
263
def _rename_path(path):
225
264
    new_name = path + '.OLD.%s' % time.time()
226
 
    log.warn('Renaming %s into %s', path, new_name)
227
 
    try:
228
 
        from setuptools.sandbox import DirectorySandbox
229
 
        def _violation(*args):
230
 
            pass
231
 
        DirectorySandbox._violation = _violation
232
 
    except ImportError:
233
 
        pass
234
 
 
 
265
    log.warn('Renaming %s to %s', path, new_name)
235
266
    os.rename(path, new_name)
236
267
    return new_name
237
268
 
249
280
        log.warn('Could not locate setuptools*.egg-info')
250
281
        return
251
282
 
252
 
    log.warn('Removing elements out of the way...')
 
283
    log.warn('Moving elements out of the way...')
253
284
    pkg_info = os.path.join(placeholder, file)
254
285
    if os.path.isdir(pkg_info):
255
286
        patched = _patch_egg_dir(pkg_info)
269
300
                     'Setuptools distribution', element)
270
301
    return True
271
302
 
 
303
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
 
304
 
272
305
 
273
306
def _after_install(dist):
274
307
    log.warn('After install bootstrap.')
275
308
    placeholder = dist.get_command_obj('install').install_purelib
276
309
    _create_fake_setuptools_pkg_info(placeholder)
277
310
 
 
311
 
278
312
def _create_fake_setuptools_pkg_info(placeholder):
279
313
    if not placeholder or not os.path.exists(placeholder):
280
314
        log.warn('Could not find the install location')
281
315
        return
282
316
    pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
283
 
    setuptools_file = 'setuptools-0.6c9-py%s.egg-info' % pyver
 
317
    setuptools_file = 'setuptools-%s-py%s.egg-info' % \
 
318
            (SETUPTOOLS_FAKED_VERSION, pyver)
284
319
    pkg_info = os.path.join(placeholder, setuptools_file)
285
320
    if os.path.exists(pkg_info):
286
321
        log.warn('%s already exists', pkg_info)
287
322
        return
 
323
 
288
324
    log.warn('Creating %s', pkg_info)
289
 
    f = open(pkg_info, 'w')
 
325
    try:
 
326
        f = open(pkg_info, 'w')
 
327
    except EnvironmentError:
 
328
        log.warn("Don't have permissions to write %s, skipping", pkg_info)
 
329
        return
290
330
    try:
291
331
        f.write(SETUPTOOLS_PKG_INFO)
292
332
    finally:
293
333
        f.close()
 
334
 
294
335
    pth_file = os.path.join(placeholder, 'setuptools.pth')
295
336
    log.warn('Creating %s', pth_file)
296
337
    f = open(pth_file, 'w')
299
340
    finally:
300
341
        f.close()
301
342
 
 
343
_create_fake_setuptools_pkg_info = _no_sandbox(
 
344
    _create_fake_setuptools_pkg_info
 
345
)
 
346
 
302
347
 
303
348
def _patch_egg_dir(path):
304
349
    # let's check if it's already patched
318
363
        f.close()
319
364
    return True
320
365
 
 
366
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
 
367
 
321
368
 
322
369
def _before_install():
323
370
    log.warn('Before install bootstrap.')
327
374
def _under_prefix(location):
328
375
    if 'install' not in sys.argv:
329
376
        return True
330
 
    args = sys.argv[sys.argv.index('install')+1:]
 
377
    args = sys.argv[sys.argv.index('install') + 1:]
331
378
    for index, arg in enumerate(args):
332
379
        for option in ('--root', '--prefix'):
333
380
            if arg.startswith('%s=' % option):
335
382
                return location.startswith(top_dir)
336
383
            elif arg == option:
337
384
                if len(args) > index:
338
 
                    top_dir = args[index+1]
 
385
                    top_dir = args[index + 1]
339
386
                    return location.startswith(top_dir)
340
 
            elif option == '--user' and USER_SITE is not None:
341
 
                return location.startswith(USER_SITE)
 
387
        if arg == '--user' and USER_SITE is not None:
 
388
            return location.startswith(USER_SITE)
342
389
    return True
343
390
 
344
391
 
352
399
        return
353
400
    ws = pkg_resources.working_set
354
401
    try:
355
 
        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
356
 
                                  replacement=False))
 
402
        setuptools_dist = ws.find(
 
403
            pkg_resources.Requirement.parse('setuptools', replacement=False)
 
404
            )
357
405
    except TypeError:
358
406
        # old distribute API
359
 
        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
 
407
        setuptools_dist = ws.find(
 
408
            pkg_resources.Requirement.parse('setuptools')
 
409
        )
360
410
 
361
411
    if setuptools_dist is None:
362
412
        log.warn('No setuptools distribution found')
390
440
        res = _patch_egg_dir(setuptools_location)
391
441
        if not res:
392
442
            return
393
 
    log.warn('Patched done.')
 
443
    log.warn('Patching complete.')
394
444
    _relaunch()
395
445
 
396
446
 
397
447
def _relaunch():
398
448
    log.warn('Relaunching...')
399
449
    # we have to relaunch the process
 
450
    # pip marker to avoid a relaunch bug
 
451
    _cmd1 = ['-c', 'install', '--single-version-externally-managed']
 
452
    _cmd2 = ['-c', 'install', '--record']
 
453
    if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
 
454
        sys.argv[0] = 'setup.py'
400
455
    args = [sys.executable] + sys.argv
401
456
    sys.exit(subprocess.call(args))
402
457
 
421
476
            # Extract directories with a safe mode.
422
477
            directories.append(tarinfo)
423
478
            tarinfo = copy.copy(tarinfo)
424
 
            tarinfo.mode = 448 # decimal for oct 0700
 
479
            tarinfo.mode = 448  # decimal for oct 0700
425
480
        self.extract(tarinfo, path)
426
481
 
427
482
    # Reverse sort directories.
448
503
                self._dbg(1, "tarfile: %s" % e)
449
504
 
450
505
 
451
 
def main(argv, version=DEFAULT_VERSION):
 
506
def _build_install_args(options):
 
507
    """
 
508
    Build the arguments to 'python setup.py install' on the distribute package
 
509
    """
 
510
    install_args = []
 
511
    if options.user_install:
 
512
        if sys.version_info < (2, 6):
 
513
            log.warn("--user requires Python 2.6 or later")
 
514
            raise SystemExit(1)
 
515
        install_args.append('--user')
 
516
    return install_args
 
517
 
 
518
def _parse_args():
 
519
    """
 
520
    Parse the command line for options
 
521
    """
 
522
    parser = optparse.OptionParser()
 
523
    parser.add_option(
 
524
        '--user', dest='user_install', action='store_true', default=False,
 
525
        help='install in user site package (requires Python 2.6 or later)')
 
526
    parser.add_option(
 
527
        '--download-base', dest='download_base', metavar="URL",
 
528
        default=DEFAULT_URL,
 
529
        help='alternative URL from where to download the distribute package')
 
530
    options, args = parser.parse_args()
 
531
    # positional arguments are ignored
 
532
    return options
 
533
 
 
534
def main(version=DEFAULT_VERSION):
452
535
    """Install or upgrade setuptools and EasyInstall"""
453
 
    tarball = download_setuptools()
454
 
    _install(tarball)
455
 
 
 
536
    options = _parse_args()
 
537
    tarball = download_setuptools(download_base=options.download_base)
 
538
    return _install(tarball, _build_install_args(options))
456
539
 
457
540
if __name__ == '__main__':
458
 
    main(sys.argv[1:])
 
541
    sys.exit(main())