Show
Ignore:
Timestamp:
09/10/10 21:52:47 (21 months ago)
Author:
mauro
Message:

update bootstrap.py

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • plone4bio.buildout/trunk/bootstrap.py

    r2 r164  
    11############################################################################## 
    22# 
    3 # Copyright (c) 2006 Zope Corporation and Contributors. 
     3# Copyright (c) 2006 Zope Foundation and Contributors. 
    44# All Rights Reserved. 
    55# 
     
    1717The script accepts buildout command-line options, so you can 
    1818use the -c option to specify an alternate configuration file. 
    19  
    20 $Id$ 
    2119""" 
    2220 
    23 import os, shutil, sys, tempfile, urllib2 
    24  
    25 tmpeggs = tempfile.mkdtemp() 
     21import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess 
     22from optparse import OptionParser 
     23 
     24if sys.platform == 'win32': 
     25    def quote(c): 
     26        if ' ' in c: 
     27            return '"%s"' % c # work around spawn lamosity on windows 
     28        else: 
     29            return c 
     30else: 
     31    quote = str 
     32 
     33# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. 
     34stdout, stderr = subprocess.Popen( 
     35    [sys.executable, '-Sc', 
     36     'try:\n' 
     37     '    import ConfigParser\n' 
     38     'except ImportError:\n' 
     39     '    print 1\n' 
     40     'else:\n' 
     41     '    print 0\n'], 
     42    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 
     43has_broken_dash_S = bool(int(stdout.strip())) 
     44 
     45# In order to be more robust in the face of system Pythons, we want to 
     46# run without site-packages loaded.  This is somewhat tricky, in 
     47# particular because Python 2.6's distutils imports site, so starting 
     48# with the -S flag is not sufficient.  However, we'll start with that: 
     49if not has_broken_dash_S and 'site' in sys.modules: 
     50    # We will restart with python -S. 
     51    args = sys.argv[:] 
     52    args[0:0] = [sys.executable, '-S'] 
     53    args = map(quote, args) 
     54    os.execv(sys.executable, args) 
     55# Now we are running with -S.  We'll get the clean sys.path, import site 
     56# because distutils will do it later, and then reset the path and clean 
     57# out any namespace packages from site-packages that might have been 
     58# loaded by .pth files. 
     59clean_path = sys.path[:] 
     60import site 
     61sys.path[:] = clean_path 
     62for k, v in sys.modules.items(): 
     63    if (hasattr(v, '__path__') and 
     64        len(v.__path__)==1 and 
     65        not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): 
     66        # This is a namespace package.  Remove it. 
     67        sys.modules.pop(k) 
     68 
     69is_jython = sys.platform.startswith('java') 
     70 
     71setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' 
     72distribute_source = 'http://python-distribute.org/distribute_setup.py' 
     73 
     74# parsing arguments 
     75def normalize_to_url(option, opt_str, value, parser): 
     76    if value: 
     77        if '://' not in value: # It doesn't smell like a URL. 
     78            value = 'file://%s' % ( 
     79                urllib.pathname2url( 
     80                    os.path.abspath(os.path.expanduser(value))),) 
     81        if opt_str == '--download-base' and not value.endswith('/'): 
     82            # Download base needs a trailing slash to make the world happy. 
     83            value += '/' 
     84    else: 
     85        value = None 
     86    name = opt_str[2:].replace('-', '_') 
     87    setattr(parser.values, name, value) 
     88 
     89usage = '''\ 
     90[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] 
     91 
     92Bootstraps a buildout-based project. 
     93 
     94Simply run this script in a directory containing a buildout.cfg, using the 
     95Python that you want bin/buildout to use. 
     96 
     97Note that by using --setup-source and --download-base to point to 
     98local resources, you can keep this script from going over the network. 
     99''' 
     100 
     101parser = OptionParser(usage=usage) 
     102parser.add_option("-v", "--version", dest="version", 
     103                          help="use a specific zc.buildout version") 
     104parser.add_option("-d", "--distribute", 
     105                   action="store_true", dest="use_distribute", default=False, 
     106                   help="Use Distribute rather than Setuptools.") 
     107parser.add_option("--setup-source", action="callback", dest="setup_source", 
     108                  callback=normalize_to_url, nargs=1, type="string", 
     109                  help=("Specify a URL or file location for the setup file. " 
     110                        "If you use Setuptools, this will default to " + 
     111                        setuptools_source + "; if you use Distribute, this " 
     112                        "will default to " + distribute_source +".")) 
     113parser.add_option("--download-base", action="callback", dest="download_base", 
     114                  callback=normalize_to_url, nargs=1, type="string", 
     115                  help=("Specify a URL or directory for downloading " 
     116                        "zc.buildout and either Setuptools or Distribute. " 
     117                        "Defaults to PyPI.")) 
     118parser.add_option("--eggs", 
     119                  help=("Specify a directory for storing eggs.  Defaults to " 
     120                        "a temporary directory that is deleted when the " 
     121                        "bootstrap script completes.")) 
     122parser.add_option("-t", "--accept-buildout-test-releases", 
     123                  dest='accept_buildout_test_releases', 
     124                  action="store_true", default=False, 
     125                  help=("Normally, if you do not specify a --version, the " 
     126                        "bootstrap script and buildout gets the newest " 
     127                        "*final* versions of zc.buildout and its recipes and " 
     128                        "extensions for you.  If you use this flag, " 
     129                        "bootstrap and buildout will get the newest releases " 
     130                        "even if they are alphas or betas.")) 
     131parser.add_option("-c", None, action="store", dest="config_file", 
     132                   help=("Specify the path to the buildout configuration " 
     133                         "file to be used.")) 
     134 
     135options, args = parser.parse_args() 
     136 
     137# if -c was provided, we push it back into args for buildout's main function 
     138if options.config_file is not None: 
     139    args += ['-c', options.config_file] 
     140 
     141if options.eggs: 
     142    eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) 
     143else: 
     144    eggs_dir = tempfile.mkdtemp() 
     145 
     146if options.setup_source is None: 
     147    if options.use_distribute: 
     148        options.setup_source = distribute_source 
     149    else: 
     150        options.setup_source = setuptools_source 
     151 
     152if options.accept_buildout_test_releases: 
     153    args.append('buildout:accept-buildout-test-releases=true') 
     154args.append('bootstrap') 
    26155 
    27156try: 
    28157    import pkg_resources 
     158    import setuptools # A flag.  Sometimes pkg_resources is installed alone. 
     159    if not hasattr(pkg_resources, '_distribute'): 
     160        raise ImportError 
    29161except ImportError: 
     162    ez_code = urllib2.urlopen( 
     163        options.setup_source).read().replace('\r\n', '\n') 
    30164    ez = {} 
    31     exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' 
    32                          ).read() in ez 
    33     ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) 
    34  
     165    exec ez_code in ez 
     166    setup_args = dict(to_dir=eggs_dir, download_delay=0) 
     167    if options.download_base: 
     168        setup_args['download_base'] = options.download_base 
     169    if options.use_distribute: 
     170        setup_args['no_fake'] = True 
     171    ez['use_setuptools'](**setup_args) 
     172    reload(sys.modules['pkg_resources']) 
    35173    import pkg_resources 
    36  
    37 cmd = 'from setuptools.command.easy_install import main; main()' 
    38 if sys.platform == 'win32': 
    39     cmd = '"%s"' % cmd # work around spawn lamosity on windows 
    40  
     174    # This does not (always?) update the default working set.  We will 
     175    # do it. 
     176    for path in sys.path: 
     177        if path not in pkg_resources.working_set.entries: 
     178            pkg_resources.working_set.add_entry(path) 
     179 
     180cmd = [quote(sys.executable), 
     181       '-c', 
     182       quote('from setuptools.command.easy_install import main; main()'), 
     183       '-mqNxd', 
     184       quote(eggs_dir)] 
     185 
     186if not has_broken_dash_S: 
     187    cmd.insert(1, '-S') 
     188 
     189find_links = options.download_base 
     190if not find_links: 
     191    find_links = os.environ.get('bootstrap-testing-find-links') 
     192if find_links: 
     193    cmd.extend(['-f', quote(find_links)]) 
     194 
     195if options.use_distribute: 
     196    setup_requirement = 'distribute' 
     197else: 
     198    setup_requirement = 'setuptools' 
    41199ws = pkg_resources.working_set 
    42 assert os.spawnle( 
    43     os.P_WAIT, sys.executable, sys.executable, 
    44     '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', 
    45     dict(os.environ, 
    46          PYTHONPATH= 
    47          ws.find(pkg_resources.Requirement.parse('setuptools')).location 
    48          ), 
    49     ) == 0 
    50  
    51 ws.add_entry(tmpeggs) 
    52 ws.require('zc.buildout') 
     200setup_requirement_path = ws.find( 
     201    pkg_resources.Requirement.parse(setup_requirement)).location 
     202env = dict( 
     203    os.environ, 
     204    PYTHONPATH=setup_requirement_path) 
     205 
     206requirement = 'zc.buildout' 
     207version = options.version 
     208if version is None and not options.accept_buildout_test_releases: 
     209    # Figure out the most recent final version of zc.buildout. 
     210    import setuptools.package_index 
     211    _final_parts = '*final-', '*final' 
     212    def _final_version(parsed_version): 
     213        for part in parsed_version: 
     214            if (part[:1] == '*') and (part not in _final_parts): 
     215                return False 
     216        return True 
     217    index = setuptools.package_index.PackageIndex( 
     218        search_path=[setup_requirement_path]) 
     219    if find_links: 
     220        index.add_find_links((find_links,)) 
     221    req = pkg_resources.Requirement.parse(requirement) 
     222    if index.obtain(req) is not None: 
     223        best = [] 
     224        bestv = None 
     225        for dist in index[req.project_name]: 
     226            distv = dist.parsed_version 
     227            if _final_version(distv): 
     228                if bestv is None or distv > bestv: 
     229                    best = [dist] 
     230                    bestv = distv 
     231                elif distv == bestv: 
     232                    best.append(dist) 
     233        if best: 
     234            best.sort() 
     235            version = best[-1].version 
     236if version: 
     237    requirement = '=='.join((requirement, version)) 
     238cmd.append(requirement) 
     239 
     240if is_jython: 
     241    import subprocess 
     242    exitcode = subprocess.Popen(cmd, env=env).wait() 
     243else: # Windows prefers this, apparently; otherwise we would prefer subprocess 
     244    exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) 
     245if exitcode != 0: 
     246    sys.stdout.flush() 
     247    sys.stderr.flush() 
     248    print ("An error occurred when trying to install zc.buildout. " 
     249           "Look above this message for any errors that " 
     250           "were output by easy_install.") 
     251    sys.exit(exitcode) 
     252 
     253ws.add_entry(eggs_dir) 
     254ws.require(requirement) 
    53255import zc.buildout.buildout 
    54 zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) 
    55 shutil.rmtree(tmpeggs) 
     256zc.buildout.buildout.main(args) 
     257if not options.eggs: # clean up temporary egg directory 
     258    shutil.rmtree(eggs_dir)