eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 ##############################################################################
       
     2 #
       
     3 # Copyright (c) 2005-2009 Zope Corporation and Contributors.
       
     4 # All Rights Reserved.
       
     5 #
       
     6 # This software is subject to the provisions of the Zope Public License,
       
     7 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    11 # FOR A PARTICULAR PURPOSE.
       
    12 #
       
    13 ##############################################################################
       
    14 """Buildout main script
       
    15 """
       
    16 
       
    17 from rmtree import rmtree
       
    18 try:
       
    19     from hashlib import md5
       
    20 except ImportError:
       
    21     # Python 2.4 and older
       
    22     from md5 import md5
       
    23 
       
    24 import ConfigParser
       
    25 import copy
       
    26 import distutils.errors
       
    27 import glob
       
    28 import itertools
       
    29 import logging
       
    30 import os
       
    31 import pkg_resources
       
    32 import re
       
    33 import shutil
       
    34 import sys
       
    35 import tempfile
       
    36 import UserDict
       
    37 import warnings
       
    38 import zc.buildout
       
    39 import zc.buildout.download
       
    40 import zc.buildout.easy_install
       
    41 
       
    42 
       
    43 realpath = zc.buildout.easy_install.realpath
       
    44 
       
    45 pkg_resources_loc = pkg_resources.working_set.find(
       
    46     pkg_resources.Requirement.parse('setuptools')).location
       
    47 
       
    48 _isurl = re.compile('([a-zA-Z0-9+.-]+)://').match
       
    49 
       
    50 is_jython = sys.platform.startswith('java')
       
    51 
       
    52 if is_jython:
       
    53     import subprocess
       
    54 
       
    55 _sys_executable_has_broken_dash_S = (
       
    56     zc.buildout.easy_install._has_broken_dash_S(sys.executable))
       
    57 
       
    58 class MissingOption(zc.buildout.UserError, KeyError):
       
    59     """A required option was missing.
       
    60     """
       
    61 
       
    62 class MissingSection(zc.buildout.UserError, KeyError):
       
    63     """A required section is missing.
       
    64     """
       
    65 
       
    66     def __str__(self):
       
    67         return "The referenced section, %r, was not defined." % self[0]
       
    68 
       
    69 
       
    70 def _annotate_section(section, note):
       
    71     for key in section:
       
    72         section[key] = (section[key], note)
       
    73     return section
       
    74 
       
    75 def _annotate(data, note):
       
    76     for key in data:
       
    77         data[key] = _annotate_section(data[key], note)
       
    78     return data
       
    79 
       
    80 def _print_annotate(data):
       
    81     sections = data.keys()
       
    82     sections.sort()
       
    83     print
       
    84     print "Annotated sections"
       
    85     print "="*len("Annotated sections")
       
    86     for section in sections:
       
    87         print
       
    88         print '[%s]' % section
       
    89         keys = data[section].keys()
       
    90         keys.sort()
       
    91         for key in keys:
       
    92             value, notes = data[section][key]
       
    93             keyvalue = "%s= %s" % (key, value)
       
    94             print keyvalue
       
    95             line = '   '
       
    96             for note in notes.split():
       
    97                 if note == '[+]':
       
    98                     line = '+= '
       
    99                 elif note == '[-]':
       
   100                     line = '-= '
       
   101                 else:
       
   102                     print line, note
       
   103                     line = '   '
       
   104     print
       
   105 
       
   106 
       
   107 def _unannotate_section(section):
       
   108     for key in section:
       
   109         value, note = section[key]
       
   110         section[key] = value
       
   111     return section
       
   112 
       
   113 def _unannotate(data):
       
   114     for key in data:
       
   115         data[key] = _unannotate_section(data[key])
       
   116     return data
       
   117 
       
   118 _buildout_default_options = _annotate_section({
       
   119     'accept-buildout-test-releases': 'false',
       
   120     'allow-hosts': '*',
       
   121     'allow-picked-versions': 'true',
       
   122     'allowed-eggs-from-site-packages': '*',
       
   123     'bin-directory': 'bin',
       
   124     'develop-eggs-directory': 'develop-eggs',
       
   125     'eggs-directory': 'eggs',
       
   126     'executable': sys.executable,
       
   127     'exec-sitecustomize': 'true',
       
   128     'find-links': '',
       
   129     'include-site-packages': 'true',
       
   130     'install-from-cache': 'false',
       
   131     'installed': '.installed.cfg',
       
   132     'log-format': '',
       
   133     'log-level': 'INFO',
       
   134     'newest': 'true',
       
   135     'offline': 'false',
       
   136     'parts-directory': 'parts',
       
   137     'prefer-final': 'false',
       
   138     'python': 'buildout',
       
   139     'relative-paths': 'false',
       
   140     'socket-timeout': '',
       
   141     'unzip': 'false',
       
   142     'use-dependency-links': 'true',
       
   143     }, 'DEFAULT_VALUE')
       
   144 
       
   145 
       
   146 class Buildout(UserDict.DictMixin):
       
   147 
       
   148     def __init__(self, config_file, cloptions,
       
   149                  user_defaults=True, windows_restart=False, command=None):
       
   150 
       
   151         __doing__ = 'Initializing.'
       
   152 
       
   153         self.__windows_restart = windows_restart
       
   154 
       
   155         # default options
       
   156         data = dict(buildout=_buildout_default_options.copy())
       
   157         self._buildout_dir = os.getcwd()
       
   158 
       
   159         if not _isurl(config_file):
       
   160             config_file = os.path.abspath(config_file)
       
   161             base = os.path.dirname(config_file)
       
   162             if not os.path.exists(config_file):
       
   163                 if command == 'init':
       
   164                     print 'Creating %r.' % config_file
       
   165                     open(config_file, 'w').write('[buildout]\nparts = \n')
       
   166                 elif command == 'setup':
       
   167                     # Sigh. This model of a buildout instance
       
   168                     # with methods is breaking down. :(
       
   169                     config_file = None
       
   170                     data['buildout']['directory'] = ('.', 'COMPUTED_VALUE')
       
   171                 else:
       
   172                     raise zc.buildout.UserError(
       
   173                         "Couldn't open %s" % config_file)
       
   174 
       
   175             if config_file:
       
   176                 data['buildout']['directory'] = (os.path.dirname(config_file),
       
   177                     'COMPUTED_VALUE')
       
   178         else:
       
   179             base = None
       
   180 
       
   181 
       
   182         cloptions = dict(
       
   183             (section, dict((option, (value, 'COMMAND_LINE_VALUE'))
       
   184                            for (_, option, value) in v))
       
   185             for (section, v) in itertools.groupby(sorted(cloptions),
       
   186                                                   lambda v: v[0])
       
   187             )
       
   188         override = cloptions.get('buildout', {}).copy()
       
   189 
       
   190         # load user defaults, which override defaults
       
   191         if user_defaults:
       
   192             user_config = os.path.join(os.path.expanduser('~'),
       
   193                                        '.buildout', 'default.cfg')
       
   194             if os.path.exists(user_config):
       
   195                 _update(data, _open(os.path.dirname(user_config), user_config,
       
   196                                     [], data['buildout'].copy(), override))
       
   197 
       
   198         # load configuration files
       
   199         if config_file:
       
   200             _update(data, _open(os.path.dirname(config_file), config_file, [],
       
   201                                 data['buildout'].copy(), override))
       
   202 
       
   203         # apply command-line options
       
   204         _update(data, cloptions)
       
   205 
       
   206         self._annotated = copy.deepcopy(data)
       
   207         self._raw = _unannotate(data)
       
   208         self._data = {}
       
   209         self._parts = []
       
   210         # provide some defaults before options are parsed
       
   211         # because while parsing options those attributes might be
       
   212         # used already (Gottfried Ganssauge)
       
   213         buildout_section = data['buildout']
       
   214 
       
   215         # Try to make sure we have absolute paths for standard
       
   216         # directories. We do this before doing substitutions, in case
       
   217         # a one of these gets read by another section.  If any
       
   218         # variable references are used though, we leave it as is in
       
   219         # _buildout_path.
       
   220         if 'directory' in buildout_section:
       
   221             self._buildout_dir = buildout_section['directory']
       
   222             for name in ('bin', 'parts', 'eggs', 'develop-eggs'):
       
   223                 d = self._buildout_path(buildout_section[name+'-directory'])
       
   224                 buildout_section[name+'-directory'] = d
       
   225 
       
   226         # Attributes on this buildout object shouldn't be used by
       
   227         # recipes in their __init__.  It can cause bugs, because the
       
   228         # recipes will be instantiated below (``options = self['buildout']``)
       
   229         # before this has completed initializing.  These attributes are
       
   230         # left behind for legacy support but recipe authors should
       
   231         # beware of using them.  A better practice is for a recipe to
       
   232         # use the buildout['buildout'] options.
       
   233         links = buildout_section['find-links']
       
   234         self._links = links and links.split() or ()
       
   235         allow_hosts = buildout_section['allow-hosts'].split('\n')
       
   236         self._allow_hosts = tuple([host.strip() for host in allow_hosts
       
   237                                    if host.strip() != ''])
       
   238         self._logger = logging.getLogger('zc.buildout')
       
   239         self.offline = (buildout_section['offline'] == 'true')
       
   240         self.newest = (buildout_section['newest'] == 'true')
       
   241         self.accept_buildout_test_releases = (
       
   242             buildout_section['accept-buildout-test-releases'] == 'true')
       
   243 
       
   244         ##################################################################
       
   245         ## WARNING!!!
       
   246         ## ALL ATTRIBUTES MUST HAVE REASONABLE DEFAULTS AT THIS POINT
       
   247         ## OTHERWISE ATTRIBUTEERRORS MIGHT HAPPEN ANY TIME FROM RECIPES.
       
   248         ## RECIPES SHOULD GENERALLY USE buildout['buildout'] OPTIONS, NOT
       
   249         ## BUILDOUT ATTRIBUTES.
       
   250         ##################################################################
       
   251         # initialize some attrs and buildout directories.
       
   252         options = self['buildout']
       
   253 
       
   254         # now reinitialize
       
   255         links = options.get('find-links', '')
       
   256         self._links = links and links.split() or ()
       
   257 
       
   258         allow_hosts = options['allow-hosts'].split('\n')
       
   259         self._allow_hosts = tuple([host.strip() for host in allow_hosts
       
   260                                    if host.strip() != ''])
       
   261 
       
   262         self._buildout_dir = options['directory']
       
   263 
       
   264         # Make sure we have absolute paths for standard directories.  We do this
       
   265         # a second time here in case someone overrode these in their configs.
       
   266         for name in ('bin', 'parts', 'eggs', 'develop-eggs'):
       
   267             d = self._buildout_path(options[name+'-directory'])
       
   268             options[name+'-directory'] = d
       
   269 
       
   270         if options['installed']:
       
   271             options['installed'] = os.path.join(options['directory'],
       
   272                                                 options['installed'])
       
   273 
       
   274         self._setup_logging()
       
   275 
       
   276         versions = options.get('versions')
       
   277         if versions:
       
   278             zc.buildout.easy_install.default_versions(dict(self[versions]))
       
   279 
       
   280 
       
   281         self.offline = options.get_bool('offline')
       
   282         if self.offline:
       
   283             options['newest'] = 'false'
       
   284         self.newest = options.get_bool('newest')
       
   285         zc.buildout.easy_install.prefer_final(
       
   286             options.get_bool('prefer-final'))
       
   287         self.accept_buildout_test_releases = options.get_bool(
       
   288             'accept-buildout-test-releases')
       
   289         zc.buildout.easy_install.use_dependency_links(
       
   290             options.get_bool('use-dependency-links'))
       
   291         zc.buildout.easy_install.allow_picked_versions(
       
   292             options.get_bool('allow-picked-versions'))
       
   293         zc.buildout.easy_install.install_from_cache(
       
   294             options.get_bool('install-from-cache'))
       
   295         zc.buildout.easy_install.always_unzip(options.get_bool('unzip'))
       
   296         allowed_eggs = tuple(name.strip() for name in options[
       
   297             'allowed-eggs-from-site-packages'].split('\n'))
       
   298         self.include_site_packages = options.get_bool('include-site-packages')
       
   299         self.exec_sitecustomize = options.get_bool('exec-sitecustomize')
       
   300         if (_sys_executable_has_broken_dash_S and
       
   301             (not self.include_site_packages or allowed_eggs != ('*',))):
       
   302             # We can't do this if the executable has a broken -S.
       
   303             warnings.warn(zc.buildout.easy_install.BROKEN_DASH_S_WARNING)
       
   304             self.include_site_packages = True
       
   305         zc.buildout.easy_install.allowed_eggs_from_site_packages(allowed_eggs)
       
   306         zc.buildout.easy_install.include_site_packages(
       
   307             self.include_site_packages)
       
   308 
       
   309         download_cache = options.get('download-cache')
       
   310         if download_cache:
       
   311             download_cache = os.path.join(options['directory'], download_cache)
       
   312             if not os.path.isdir(download_cache):
       
   313                 raise zc.buildout.UserError(
       
   314                     'The specified download cache:\n'
       
   315                     '%r\n'
       
   316                     "Doesn't exist.\n"
       
   317                     % download_cache)
       
   318             download_cache = os.path.join(download_cache, 'dist')
       
   319             if not os.path.isdir(download_cache):
       
   320                 os.mkdir(download_cache)
       
   321 
       
   322             zc.buildout.easy_install.download_cache(download_cache)
       
   323 
       
   324         # "Use" each of the defaults so they aren't reported as unused options.
       
   325         for name in _buildout_default_options:
       
   326             options[name]
       
   327 
       
   328         # Do the same for extends-cache which is not among the defaults but
       
   329         # wasn't recognized as having been used since it was used before
       
   330         # tracking was turned on.
       
   331         options.get('extends-cache')
       
   332 
       
   333         os.chdir(options['directory'])
       
   334 
       
   335     def _buildout_path(self, name):
       
   336         if '${' in name:
       
   337             return name
       
   338         return os.path.join(self._buildout_dir, name)
       
   339 
       
   340     def bootstrap(self, args):
       
   341         __doing__ = 'Bootstrapping.'
       
   342 
       
   343         self._setup_directories()
       
   344 
       
   345         options = self['buildout']
       
   346 
       
   347         # Get a base working set for our distributions that corresponds to the
       
   348         # stated desires in the configuration.
       
   349         distributions = ['setuptools', 'zc.buildout']
       
   350         if options.get('offline') == 'true':
       
   351             ws = zc.buildout.easy_install.working_set(
       
   352                 distributions, options['executable'],
       
   353                 [options['develop-eggs-directory'],
       
   354                  options['eggs-directory']],
       
   355                 prefer_final=not self.accept_buildout_test_releases,
       
   356                 )
       
   357         else:
       
   358             ws = zc.buildout.easy_install.install(
       
   359                 distributions, options['eggs-directory'],
       
   360                 links=self._links,
       
   361                 index=options.get('index'),
       
   362                 executable=options['executable'],
       
   363                 path=[options['develop-eggs-directory']],
       
   364                 newest=self.newest,
       
   365                 allow_hosts=self._allow_hosts,
       
   366                 prefer_final=not self.accept_buildout_test_releases,
       
   367                 )
       
   368 
       
   369         # Now copy buildout and setuptools eggs, and record destination eggs:
       
   370         entries = []
       
   371         for name in 'setuptools', 'zc.buildout':
       
   372             r = pkg_resources.Requirement.parse(name)
       
   373             dist = ws.find(r)
       
   374             if dist.precedence == pkg_resources.DEVELOP_DIST:
       
   375                 dest = os.path.join(self['buildout']['develop-eggs-directory'],
       
   376                                     name+'.egg-link')
       
   377                 open(dest, 'w').write(dist.location)
       
   378                 entries.append(dist.location)
       
   379             else:
       
   380                 dest = os.path.join(self['buildout']['eggs-directory'],
       
   381                                     os.path.basename(dist.location))
       
   382                 entries.append(dest)
       
   383                 if not os.path.exists(dest):
       
   384                     if os.path.isdir(dist.location):
       
   385                         shutil.copytree(dist.location, dest)
       
   386                     else:
       
   387                         shutil.copy2(dist.location, dest)
       
   388 
       
   389         # Create buildout script.
       
   390         # Ideally the (possibly) new version of buildout would get a
       
   391         # chance to write the script.  Not sure how to do that.
       
   392         ws = pkg_resources.WorkingSet(entries)
       
   393         ws.require('zc.buildout')
       
   394         partsdir = os.path.join(options['parts-directory'], 'buildout')
       
   395         if not os.path.exists(partsdir):
       
   396             os.mkdir(partsdir)
       
   397         # (Honor the relative-paths option.)
       
   398         relative_paths = options.get('relative-paths', 'false')
       
   399         if relative_paths == 'true':
       
   400             relative_paths = options['directory']
       
   401         else:
       
   402             assert relative_paths == 'false'
       
   403             relative_paths = ''
       
   404         if (self.accept_buildout_test_releases and
       
   405             self._annotated['buildout']['accept-buildout-test-releases'][1] ==
       
   406             'COMMAND_LINE_VALUE'):
       
   407             # Bootstrap was called with '--accept-buildout-test-releases'.
       
   408             # Continue to honor that setting.
       
   409             script_initialization = _early_release_initialization_code
       
   410         else:
       
   411             script_initialization = ''
       
   412         zc.buildout.easy_install.sitepackage_safe_scripts(
       
   413             options['bin-directory'], ws, options['executable'], partsdir,
       
   414             reqs=['zc.buildout'], relative_paths=relative_paths,
       
   415             include_site_packages=self.include_site_packages,
       
   416             script_initialization=script_initialization,
       
   417             exec_sitecustomize=self.exec_sitecustomize,
       
   418             )
       
   419 
       
   420     init = bootstrap
       
   421 
       
   422     def install(self, install_args):
       
   423         __doing__ = 'Installing.'
       
   424 
       
   425         self._load_extensions()
       
   426         self._setup_directories()
       
   427 
       
   428         # Add develop-eggs directory to path so that it gets searched
       
   429         # for eggs:
       
   430         sys.path.insert(0, self['buildout']['develop-eggs-directory'])
       
   431 
       
   432         # Check for updates. This could cause the process to be restarted.
       
   433         self._maybe_upgrade()
       
   434 
       
   435         # load installed data
       
   436         (installed_part_options, installed_exists
       
   437          )= self._read_installed_part_options()
       
   438 
       
   439         # Remove old develop eggs
       
   440         self._uninstall(
       
   441             installed_part_options['buildout'].get(
       
   442                 'installed_develop_eggs', '')
       
   443             )
       
   444 
       
   445         # Build develop eggs
       
   446         installed_develop_eggs = self._develop()
       
   447         installed_part_options['buildout']['installed_develop_eggs'
       
   448                                            ] = installed_develop_eggs
       
   449 
       
   450         if installed_exists:
       
   451             self._update_installed(
       
   452                 installed_develop_eggs=installed_develop_eggs)
       
   453 
       
   454         # get configured and installed part lists
       
   455         conf_parts = self['buildout']['parts']
       
   456         conf_parts = conf_parts and conf_parts.split() or []
       
   457         installed_parts = installed_part_options['buildout']['parts']
       
   458         installed_parts = installed_parts and installed_parts.split() or []
       
   459 
       
   460         if install_args:
       
   461             install_parts = install_args
       
   462             uninstall_missing = False
       
   463         else:
       
   464             install_parts = conf_parts
       
   465             uninstall_missing = True
       
   466 
       
   467         # load and initialize recipes
       
   468         [self[part]['recipe'] for part in install_parts]
       
   469         if not install_args:
       
   470             install_parts = self._parts
       
   471 
       
   472         if self._log_level < logging.DEBUG:
       
   473             sections = list(self)
       
   474             sections.sort()
       
   475             print
       
   476             print 'Configuration data:'
       
   477             for section in self._data:
       
   478                 _save_options(section, self[section], sys.stdout)
       
   479             print
       
   480 
       
   481 
       
   482         # compute new part recipe signatures
       
   483         self._compute_part_signatures(install_parts)
       
   484 
       
   485         # uninstall parts that are no-longer used or whose configs
       
   486         # have changed
       
   487         for part in reversed(installed_parts):
       
   488             if part in install_parts:
       
   489                 old_options = installed_part_options[part].copy()
       
   490                 installed_files = old_options.pop('__buildout_installed__')
       
   491                 new_options = self.get(part)
       
   492                 if old_options == new_options:
       
   493                     # The options are the same, but are all of the
       
   494                     # installed files still there?  If not, we should
       
   495                     # reinstall.
       
   496                     if not installed_files:
       
   497                         continue
       
   498                     for f in installed_files.split('\n'):
       
   499                         if not os.path.exists(self._buildout_path(f)):
       
   500                             break
       
   501                     else:
       
   502                         continue
       
   503 
       
   504                 # output debugging info
       
   505                 if self._logger.getEffectiveLevel() < logging.DEBUG:
       
   506                     for k in old_options:
       
   507                         if k not in new_options:
       
   508                             self._logger.debug("Part %s, dropped option %s.",
       
   509                                                part, k)
       
   510                         elif old_options[k] != new_options[k]:
       
   511                             self._logger.debug(
       
   512                                 "Part %s, option %s changed:\n%r != %r",
       
   513                                 part, k, new_options[k], old_options[k],
       
   514                                 )
       
   515                     for k in new_options:
       
   516                         if k not in old_options:
       
   517                             self._logger.debug("Part %s, new option %s.",
       
   518                                                part, k)
       
   519 
       
   520             elif not uninstall_missing:
       
   521                 continue
       
   522 
       
   523             self._uninstall_part(part, installed_part_options)
       
   524             installed_parts = [p for p in installed_parts if p != part]
       
   525 
       
   526             if installed_exists:
       
   527                 self._update_installed(parts=' '.join(installed_parts))
       
   528 
       
   529         # Check for unused buildout options:
       
   530         _check_for_unused_options_in_section(self, 'buildout')
       
   531 
       
   532         # install new parts
       
   533         for part in install_parts:
       
   534             signature = self[part].pop('__buildout_signature__')
       
   535             saved_options = self[part].copy()
       
   536             recipe = self[part].recipe
       
   537             if part in installed_parts: # update
       
   538                 need_to_save_installed = False
       
   539                 __doing__ = 'Updating %s.', part
       
   540                 self._logger.info(*__doing__)
       
   541                 old_options = installed_part_options[part]
       
   542                 old_installed_files = old_options['__buildout_installed__']
       
   543 
       
   544                 try:
       
   545                     update = recipe.update
       
   546                 except AttributeError:
       
   547                     update = recipe.install
       
   548                     self._logger.warning(
       
   549                         "The recipe for %s doesn't define an update "
       
   550                         "method. Using its install method.",
       
   551                         part)
       
   552 
       
   553                 try:
       
   554                     installed_files = self[part]._call(update)
       
   555                 except:
       
   556                     installed_parts.remove(part)
       
   557                     self._uninstall(old_installed_files)
       
   558                     if installed_exists:
       
   559                         self._update_installed(
       
   560                             parts=' '.join(installed_parts))
       
   561                     raise
       
   562 
       
   563                 old_installed_files = old_installed_files.split('\n')
       
   564                 if installed_files is None:
       
   565                     installed_files = old_installed_files
       
   566                 else:
       
   567                     if isinstance(installed_files, str):
       
   568                         installed_files = [installed_files]
       
   569                     else:
       
   570                         installed_files = list(installed_files)
       
   571 
       
   572                     need_to_save_installed = [
       
   573                         p for p in installed_files
       
   574                         if p not in old_installed_files]
       
   575 
       
   576                     if need_to_save_installed:
       
   577                         installed_files = (old_installed_files
       
   578                                            + need_to_save_installed)
       
   579 
       
   580             else: # install
       
   581                 need_to_save_installed = True
       
   582                 __doing__ = 'Installing %s.', part
       
   583                 self._logger.info(*__doing__)
       
   584                 installed_files = self[part]._call(recipe.install)
       
   585                 if installed_files is None:
       
   586                     self._logger.warning(
       
   587                         "The %s install returned None.  A path or "
       
   588                         "iterable of paths should be returned.",
       
   589                         part)
       
   590                     installed_files = ()
       
   591                 elif isinstance(installed_files, str):
       
   592                     installed_files = [installed_files]
       
   593                 else:
       
   594                     installed_files = list(installed_files)
       
   595 
       
   596             installed_part_options[part] = saved_options
       
   597             saved_options['__buildout_installed__'
       
   598                           ] = '\n'.join(installed_files)
       
   599             saved_options['__buildout_signature__'] = signature
       
   600 
       
   601             installed_parts = [p for p in installed_parts if p != part]
       
   602             installed_parts.append(part)
       
   603             _check_for_unused_options_in_section(self, part)
       
   604 
       
   605             if need_to_save_installed:
       
   606                 installed_part_options['buildout']['parts'] = (
       
   607                     ' '.join(installed_parts))
       
   608                 self._save_installed_options(installed_part_options)
       
   609                 installed_exists = True
       
   610             else:
       
   611                 assert installed_exists
       
   612                 self._update_installed(parts=' '.join(installed_parts))
       
   613 
       
   614         if installed_develop_eggs:
       
   615             if not installed_exists:
       
   616                 self._save_installed_options(installed_part_options)
       
   617         elif (not installed_parts) and installed_exists:
       
   618             os.remove(self['buildout']['installed'])
       
   619 
       
   620         self._unload_extensions()
       
   621 
       
   622     def _update_installed(self, **buildout_options):
       
   623         installed = self['buildout']['installed']
       
   624         f = open(installed, 'a')
       
   625         f.write('\n[buildout]\n')
       
   626         for option, value in buildout_options.items():
       
   627             _save_option(option, value, f)
       
   628         f.close()
       
   629 
       
   630     def _uninstall_part(self, part, installed_part_options):
       
   631         # uninstall part
       
   632         __doing__ = 'Uninstalling %s.', part
       
   633         self._logger.info(*__doing__)
       
   634 
       
   635         # run uninstall recipe
       
   636         recipe, entry = _recipe(installed_part_options[part])
       
   637         try:
       
   638             uninstaller = _install_and_load(
       
   639                 recipe, 'zc.buildout.uninstall', entry, self)
       
   640             self._logger.info('Running uninstall recipe.')
       
   641             uninstaller(part, installed_part_options[part])
       
   642         except (ImportError, pkg_resources.DistributionNotFound), v:
       
   643             pass
       
   644 
       
   645         # remove created files and directories
       
   646         self._uninstall(
       
   647             installed_part_options[part]['__buildout_installed__'])
       
   648 
       
   649     def _setup_directories(self):
       
   650         __doing__ = 'Setting up buildout directories'
       
   651 
       
   652         # Create buildout directories
       
   653         for name in ('bin', 'parts', 'eggs', 'develop-eggs'):
       
   654             d = self['buildout'][name+'-directory']
       
   655             if not os.path.exists(d):
       
   656                 self._logger.info('Creating directory %r.', d)
       
   657                 os.mkdir(d)
       
   658 
       
   659     def _develop(self):
       
   660         """Install sources by running setup.py develop on them
       
   661         """
       
   662         __doing__ = 'Processing directories listed in the develop option'
       
   663 
       
   664         develop = self['buildout'].get('develop')
       
   665         if not develop:
       
   666             return ''
       
   667 
       
   668         dest = self['buildout']['develop-eggs-directory']
       
   669         old_files = os.listdir(dest)
       
   670 
       
   671         env = dict(os.environ, PYTHONPATH=pkg_resources_loc)
       
   672         here = os.getcwd()
       
   673         try:
       
   674             try:
       
   675                 for setup in develop.split():
       
   676                     setup = self._buildout_path(setup)
       
   677                     files = glob.glob(setup)
       
   678                     if not files:
       
   679                         self._logger.warn("Couldn't develop %r (not found)",
       
   680                                           setup)
       
   681                     else:
       
   682                         files.sort()
       
   683                     for setup in files:
       
   684                         self._logger.info("Develop: %r", setup)
       
   685                         __doing__ = 'Processing develop directory %r.', setup
       
   686                         zc.buildout.easy_install.develop(setup, dest)
       
   687             except:
       
   688                 # if we had an error, we need to roll back changes, by
       
   689                 # removing any files we created.
       
   690                 self._sanity_check_develop_eggs_files(dest, old_files)
       
   691                 self._uninstall('\n'.join(
       
   692                     [os.path.join(dest, f)
       
   693                      for f in os.listdir(dest)
       
   694                      if f not in old_files
       
   695                      ]))
       
   696                 raise
       
   697 
       
   698             else:
       
   699                 self._sanity_check_develop_eggs_files(dest, old_files)
       
   700                 return '\n'.join([os.path.join(dest, f)
       
   701                                   for f in os.listdir(dest)
       
   702                                   if f not in old_files
       
   703                                   ])
       
   704 
       
   705         finally:
       
   706             os.chdir(here)
       
   707 
       
   708 
       
   709     def _sanity_check_develop_eggs_files(self, dest, old_files):
       
   710         for f in os.listdir(dest):
       
   711             if f in old_files:
       
   712                 continue
       
   713             if not (os.path.isfile(os.path.join(dest, f))
       
   714                     and f.endswith('.egg-link')):
       
   715                 self._logger.warning(
       
   716                     "Unexpected entry, %r, in develop-eggs directory.", f)
       
   717 
       
   718     def _compute_part_signatures(self, parts):
       
   719         # Compute recipe signature and add to options
       
   720         for part in parts:
       
   721             options = self.get(part)
       
   722             if options is None:
       
   723                 options = self[part] = {}
       
   724             recipe, entry = _recipe(options)
       
   725             req = pkg_resources.Requirement.parse(recipe)
       
   726             sig = _dists_sig(pkg_resources.working_set.resolve([req]))
       
   727             options['__buildout_signature__'] = ' '.join(sig)
       
   728 
       
   729     def _read_installed_part_options(self):
       
   730         old = self['buildout']['installed']
       
   731         if old and os.path.isfile(old):
       
   732             parser = ConfigParser.RawConfigParser()
       
   733             parser.optionxform = lambda s: s
       
   734             parser.read(old)
       
   735             result = {}
       
   736             for section in parser.sections():
       
   737                 options = {}
       
   738                 for option, value in parser.items(section):
       
   739                     if '%(' in value:
       
   740                         for k, v in _spacey_defaults:
       
   741                             value = value.replace(k, v)
       
   742                     options[option] = value
       
   743                 result[section] = Options(self, section, options)
       
   744 
       
   745             return result, True
       
   746         else:
       
   747             return ({'buildout': Options(self, 'buildout', {'parts': ''})},
       
   748                     False,
       
   749                     )
       
   750 
       
   751     def _uninstall(self, installed):
       
   752         for f in installed.split('\n'):
       
   753             if not f:
       
   754                 continue
       
   755             f = self._buildout_path(f)
       
   756             if os.path.isdir(f):
       
   757                 rmtree(f)
       
   758             elif os.path.isfile(f):
       
   759                 try:
       
   760                     os.remove(f)
       
   761                 except OSError:
       
   762                     if not (
       
   763                         sys.platform == 'win32' and
       
   764                         (realpath(os.path.join(os.path.dirname(sys.argv[0]),
       
   765                                                'buildout.exe'))
       
   766                          ==
       
   767                          realpath(f)
       
   768                          )
       
   769                         # Sigh. This is the exectable used to run the buildout
       
   770                         # and, of course, it's in use. Leave it.
       
   771                         ):
       
   772                         raise
       
   773 
       
   774     def _install(self, part):
       
   775         options = self[part]
       
   776         recipe, entry = _recipe(options)
       
   777         recipe_class = pkg_resources.load_entry_point(
       
   778             recipe, 'zc.buildout', entry)
       
   779         installed = recipe_class(self, part, options).install()
       
   780         if installed is None:
       
   781             installed = []
       
   782         elif isinstance(installed, basestring):
       
   783             installed = [installed]
       
   784         base = self._buildout_path('')
       
   785         installed = [d.startswith(base) and d[len(base):] or d
       
   786                      for d in installed]
       
   787         return ' '.join(installed)
       
   788 
       
   789 
       
   790     def _save_installed_options(self, installed_options):
       
   791         installed = self['buildout']['installed']
       
   792         if not installed:
       
   793             return
       
   794         f = open(installed, 'w')
       
   795         _save_options('buildout', installed_options['buildout'], f)
       
   796         for part in installed_options['buildout']['parts'].split():
       
   797             print >>f
       
   798             _save_options(part, installed_options[part], f)
       
   799         f.close()
       
   800 
       
   801     def _error(self, message, *args):
       
   802         raise zc.buildout.UserError(message % args)
       
   803 
       
   804     def _setup_logging(self):
       
   805         root_logger = logging.getLogger()
       
   806         self._logger = logging.getLogger('zc.buildout')
       
   807         handler = logging.StreamHandler(sys.stdout)
       
   808         log_format = self['buildout']['log-format']
       
   809         if not log_format:
       
   810             # No format specified. Use different formatter for buildout
       
   811             # and other modules, showing logger name except for buildout
       
   812             log_format = '%(name)s: %(message)s'
       
   813             buildout_handler = logging.StreamHandler(sys.stdout)
       
   814             buildout_handler.setFormatter(logging.Formatter('%(message)s'))
       
   815             self._logger.propagate = False
       
   816             self._logger.addHandler(buildout_handler)
       
   817 
       
   818         handler.setFormatter(logging.Formatter(log_format))
       
   819         root_logger.addHandler(handler)
       
   820 
       
   821         level = self['buildout']['log-level']
       
   822         if level in ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'):
       
   823             level = getattr(logging, level)
       
   824         else:
       
   825             try:
       
   826                 level = int(level)
       
   827             except ValueError:
       
   828                 self._error("Invalid logging level %s", level)
       
   829         verbosity = self['buildout'].get('verbosity', 0)
       
   830         try:
       
   831             verbosity = int(verbosity)
       
   832         except ValueError:
       
   833             self._error("Invalid verbosity %s", verbosity)
       
   834 
       
   835         level -= verbosity
       
   836         root_logger.setLevel(level)
       
   837         self._log_level = level
       
   838 
       
   839     def _maybe_upgrade(self):
       
   840         # See if buildout or setuptools need to be upgraded.
       
   841         # If they do, do the upgrade and restart the buildout process.
       
   842         __doing__ = 'Checking for upgrades.'
       
   843 
       
   844         if not self.newest:
       
   845             return
       
   846 
       
   847         options = self['buildout']
       
   848 
       
   849         specs = ['zc.buildout']
       
   850         if zc.buildout.easy_install.is_distribute:
       
   851             specs.append('distribute')
       
   852         else:
       
   853             specs.append('setuptools')
       
   854         ws = zc.buildout.easy_install.install(
       
   855             [
       
   856             (spec + ' ' + options.get(spec+'-version', '')).strip()
       
   857             for spec in specs
       
   858             ],
       
   859             options['eggs-directory'],
       
   860             links = options.get('find-links', '').split(),
       
   861             index = options.get('index'),
       
   862             path = [options['develop-eggs-directory']],
       
   863             allow_hosts = self._allow_hosts,
       
   864             prefer_final=not self.accept_buildout_test_releases,
       
   865             )
       
   866 
       
   867         upgraded = []
       
   868         for project in 'zc.buildout', 'setuptools':
       
   869             req = pkg_resources.Requirement.parse(project)
       
   870             project_location = pkg_resources.working_set.find(req).location
       
   871             if ws.find(req).location != project_location:
       
   872                 upgraded.append(ws.find(req))
       
   873 
       
   874         if not upgraded:
       
   875             return
       
   876 
       
   877         __doing__ = 'Upgrading.'
       
   878 
       
   879         should_run = realpath(
       
   880             os.path.join(os.path.abspath(options['bin-directory']),
       
   881                          'buildout')
       
   882             )
       
   883         if sys.platform == 'win32':
       
   884             should_run += '-script.py'
       
   885 
       
   886         if (realpath(os.path.abspath(sys.argv[0])) != should_run):
       
   887             self._logger.debug("Running %r.", realpath(sys.argv[0]))
       
   888             self._logger.debug("Local buildout is %r.", should_run)
       
   889             self._logger.warn("Not upgrading because not running a local "
       
   890                               "buildout command.")
       
   891             return
       
   892 
       
   893         if sys.platform == 'win32' and not self.__windows_restart:
       
   894             args = map(zc.buildout.easy_install._safe_arg, sys.argv)
       
   895             args.insert(1, '-W')
       
   896             if not __debug__:
       
   897                 args.insert(0, '-O')
       
   898             args.insert(0, zc.buildout.easy_install._safe_arg (sys.executable))
       
   899             os.execv(sys.executable, args)
       
   900 
       
   901         self._logger.info("Upgraded:\n  %s;\nrestarting.",
       
   902                           ",\n  ".join([("%s version %s"
       
   903                                        % (dist.project_name, dist.version)
       
   904                                        )
       
   905                                       for dist in upgraded
       
   906                                       ]
       
   907                                      ),
       
   908                           )
       
   909 
       
   910         # the new dist is different, so we've upgraded.
       
   911         # Update the scripts and return True
       
   912         # Ideally the new version of buildout would get a chance to write the
       
   913         # script.  Not sure how to do that.
       
   914         partsdir = os.path.join(options['parts-directory'], 'buildout')
       
   915         if os.path.exists(partsdir):
       
   916             # This is primarily for unit tests, in which .py files change too
       
   917             # fast for Python to know to regenerate the .pyc/.pyo files.
       
   918             shutil.rmtree(partsdir)
       
   919         os.mkdir(partsdir)
       
   920         if (self.accept_buildout_test_releases and
       
   921             self._annotated['buildout']['accept-buildout-test-releases'][1] ==
       
   922             'COMMAND_LINE_VALUE'):
       
   923             # Bootstrap was called with '--accept-buildout-test-releases'.
       
   924             # Continue to honor that setting.
       
   925             script_initialization = _early_release_initialization_code
       
   926         else:
       
   927             script_initialization = ''
       
   928         # (Honor the relative-paths option.)
       
   929         relative_paths = options.get('relative-paths', 'false')
       
   930         if relative_paths == 'true':
       
   931             relative_paths = options['directory']
       
   932         else:
       
   933             assert relative_paths == 'false'
       
   934             relative_paths = ''
       
   935         zc.buildout.easy_install.sitepackage_safe_scripts(
       
   936             options['bin-directory'], ws, options['executable'], partsdir,
       
   937             reqs=['zc.buildout'], relative_paths=relative_paths,
       
   938             include_site_packages=self.include_site_packages,
       
   939             script_initialization=script_initialization,
       
   940             exec_sitecustomize=self.exec_sitecustomize,
       
   941             )
       
   942 
       
   943         # Restart
       
   944         args = map(zc.buildout.easy_install._safe_arg, sys.argv)
       
   945         if not __debug__:
       
   946             args.insert(0, '-O')
       
   947         args.insert(0, zc.buildout.easy_install._safe_arg(sys.executable))
       
   948         # We want to make sure that our new site.py is used for rerunning
       
   949         # buildout, so we put the partsdir in PYTHONPATH for our restart.
       
   950         # This overrides any set PYTHONPATH, but since we generally are
       
   951         # trying to run with a completely "clean" python (only the standard
       
   952         # library) then that should be fine.
       
   953         env = os.environ.copy()
       
   954         env['PYTHONPATH'] = partsdir
       
   955         if is_jython:
       
   956             sys.exit(
       
   957                 subprocess.Popen(
       
   958                     [sys.executable] + list(args), env=env).wait())
       
   959         else:
       
   960             sys.exit(os.spawnve(os.P_WAIT, sys.executable, args, env))
       
   961 
       
   962     def _load_extensions(self):
       
   963         __doing__ = 'Loading extensions.'
       
   964         specs = self['buildout'].get('extensions', '').split()
       
   965         if specs:
       
   966             path = [self['buildout']['develop-eggs-directory']]
       
   967             if self.offline:
       
   968                 dest = None
       
   969                 path.append(self['buildout']['eggs-directory'])
       
   970             else:
       
   971                 dest = self['buildout']['eggs-directory']
       
   972                 if not os.path.exists(dest):
       
   973                     self._logger.info('Creating directory %r.', dest)
       
   974                     os.mkdir(dest)
       
   975 
       
   976             zc.buildout.easy_install.install(
       
   977                 specs, dest, path=path,
       
   978                 working_set=pkg_resources.working_set,
       
   979                 links = self['buildout'].get('find-links', '').split(),
       
   980                 index = self['buildout'].get('index'),
       
   981                 newest=self.newest, allow_hosts=self._allow_hosts,
       
   982                 prefer_final=not self.accept_buildout_test_releases)
       
   983 
       
   984             # Clear cache because extensions might now let us read pages we
       
   985             # couldn't read before.
       
   986             zc.buildout.easy_install.clear_index_cache()
       
   987 
       
   988             for ep in pkg_resources.iter_entry_points('zc.buildout.extension'):
       
   989                 ep.load()(self)
       
   990 
       
   991     def _unload_extensions(self):
       
   992         __doing__ = 'Unloading extensions.'
       
   993         specs = self['buildout'].get('extensions', '').split()
       
   994         if specs:
       
   995             for ep in pkg_resources.iter_entry_points(
       
   996                 'zc.buildout.unloadextension'):
       
   997                 ep.load()(self)
       
   998 
       
   999     def setup(self, args):
       
  1000         if not args:
       
  1001             raise zc.buildout.UserError(
       
  1002                 "The setup command requires the path to a setup script or \n"
       
  1003                 "directory containing a setup script, and its arguments."
       
  1004                 )
       
  1005         setup = args.pop(0)
       
  1006         if os.path.isdir(setup):
       
  1007             setup = os.path.join(setup, 'setup.py')
       
  1008 
       
  1009         self._logger.info("Running setup script %r.", setup)
       
  1010         setup = os.path.abspath(setup)
       
  1011 
       
  1012         fd, tsetup = tempfile.mkstemp()
       
  1013         exe = zc.buildout.easy_install._safe_arg(sys.executable)
       
  1014         try:
       
  1015             os.write(fd, zc.buildout.easy_install.runsetup_template % dict(
       
  1016                 setuptools=pkg_resources_loc,
       
  1017                 setupdir=os.path.dirname(setup),
       
  1018                 setup=setup,
       
  1019                 __file__ = setup,
       
  1020                 ))
       
  1021             if is_jython:
       
  1022                 arg_list = list()
       
  1023 
       
  1024                 for a in args:
       
  1025                     arg_list.append(zc.buildout.easy_install._safe_arg(a))
       
  1026 
       
  1027                 subprocess.Popen([exe] + list(tsetup) + arg_list).wait()
       
  1028 
       
  1029             else:
       
  1030                 os.spawnl(os.P_WAIT, sys.executable, exe, tsetup,
       
  1031                         *[zc.buildout.easy_install._safe_arg(a)
       
  1032                             for a in args])
       
  1033         finally:
       
  1034             os.close(fd)
       
  1035             os.remove(tsetup)
       
  1036 
       
  1037     runsetup = setup # backward compat.
       
  1038 
       
  1039     def annotate(self, args):
       
  1040         _print_annotate(self._annotated)
       
  1041 
       
  1042     def __getitem__(self, section):
       
  1043         __doing__ = 'Getting section %s.', section
       
  1044         try:
       
  1045             return self._data[section]
       
  1046         except KeyError:
       
  1047             pass
       
  1048 
       
  1049         try:
       
  1050             data = self._raw[section]
       
  1051         except KeyError:
       
  1052             raise MissingSection(section)
       
  1053 
       
  1054         options = Options(self, section, data)
       
  1055         self._data[section] = options
       
  1056         options._initialize()
       
  1057         return options
       
  1058 
       
  1059     def __setitem__(self, key, value):
       
  1060         raise NotImplementedError('__setitem__')
       
  1061 
       
  1062     def __delitem__(self, key):
       
  1063         raise NotImplementedError('__delitem__')
       
  1064 
       
  1065     def keys(self):
       
  1066         return self._raw.keys()
       
  1067 
       
  1068     def __iter__(self):
       
  1069         return iter(self._raw)
       
  1070 
       
  1071 
       
  1072 def _install_and_load(spec, group, entry, buildout):
       
  1073     __doing__ = 'Loading recipe %r.', spec
       
  1074     try:
       
  1075         req = pkg_resources.Requirement.parse(spec)
       
  1076 
       
  1077         buildout_options = buildout['buildout']
       
  1078         if pkg_resources.working_set.find(req) is None:
       
  1079             __doing__ = 'Installing recipe %s.', spec
       
  1080             if buildout.offline:
       
  1081                 dest = None
       
  1082                 path = [buildout_options['develop-eggs-directory'],
       
  1083                         buildout_options['eggs-directory'],
       
  1084                         ]
       
  1085             else:
       
  1086                 dest = buildout_options['eggs-directory']
       
  1087                 path = [buildout_options['develop-eggs-directory']]
       
  1088 
       
  1089             zc.buildout.easy_install.install(
       
  1090                 [spec], dest,
       
  1091                 links=buildout._links,
       
  1092                 index=buildout_options.get('index'),
       
  1093                 path=path,
       
  1094                 working_set=pkg_resources.working_set,
       
  1095                 newest=buildout.newest,
       
  1096                 allow_hosts=buildout._allow_hosts,
       
  1097                 prefer_final=not buildout.accept_buildout_test_releases)
       
  1098 
       
  1099         __doing__ = 'Loading %s recipe entry %s:%s.', group, spec, entry
       
  1100         return pkg_resources.load_entry_point(
       
  1101             req.project_name, group, entry)
       
  1102 
       
  1103     except Exception, v:
       
  1104         buildout._logger.log(
       
  1105             1,
       
  1106             "Could't load %s entry point %s\nfrom %s:\n%s.",
       
  1107             group, entry, spec, v)
       
  1108         raise
       
  1109 
       
  1110 
       
  1111 class Options(UserDict.DictMixin):
       
  1112 
       
  1113     def __init__(self, buildout, section, data):
       
  1114         self.buildout = buildout
       
  1115         self.name = section
       
  1116         self._raw = data
       
  1117         self._cooked = {}
       
  1118         self._data = {}
       
  1119 
       
  1120     def _initialize(self):
       
  1121         name = self.name
       
  1122         __doing__ = 'Initializing section %s.', name
       
  1123 
       
  1124         if '<' in self._raw:
       
  1125             self._raw = self._do_extend_raw(name, self._raw, [])
       
  1126 
       
  1127         # force substitutions
       
  1128         for k, v in self._raw.items():
       
  1129             if '${' in v:
       
  1130                 self._dosub(k, v)
       
  1131 
       
  1132         if self.name == 'buildout':
       
  1133             return # buildout section can never be a part
       
  1134 
       
  1135         recipe = self.get('recipe')
       
  1136         if not recipe:
       
  1137             return
       
  1138 
       
  1139         reqs, entry = _recipe(self._data)
       
  1140         buildout = self.buildout
       
  1141         recipe_class = _install_and_load(reqs, 'zc.buildout', entry, buildout)
       
  1142 
       
  1143         __doing__ = 'Initializing part %s.', name
       
  1144         self.recipe = recipe_class(buildout, name, self)
       
  1145         buildout._parts.append(name)
       
  1146 
       
  1147     def _do_extend_raw(self, name, data, doing):
       
  1148         if name == 'buildout':
       
  1149             return data
       
  1150         if name in doing:
       
  1151             raise zc.buildout.UserError("Infinite extending loop %r" % name)
       
  1152         doing.append(name)
       
  1153         try:
       
  1154             to_do = data.pop('<', None)
       
  1155             if to_do is None:
       
  1156                 return data
       
  1157             __doing__ = 'Loading input sections for %r', name
       
  1158 
       
  1159             result = {}
       
  1160             for iname in to_do.split('\n'):
       
  1161                 iname = iname.strip()
       
  1162                 if not iname:
       
  1163                     continue
       
  1164                 raw = self.buildout._raw.get(iname)
       
  1165                 if raw is None:
       
  1166                     raise zc.buildout.UserError("No section named %r" % iname)
       
  1167                 result.update(self._do_extend_raw(iname, raw, doing))
       
  1168 
       
  1169             result.update(data)
       
  1170             return result
       
  1171         finally:
       
  1172             assert doing.pop() == name
       
  1173 
       
  1174     def _dosub(self, option, v):
       
  1175         __doing__ = 'Getting option %s:%s.', self.name, option
       
  1176         seen = [(self.name, option)]
       
  1177         v = '$$'.join([self._sub(s, seen) for s in v.split('$$')])
       
  1178         self._cooked[option] = v
       
  1179 
       
  1180     def get(self, option, default=None, seen=None):
       
  1181         try:
       
  1182             return self._data[option]
       
  1183         except KeyError:
       
  1184             pass
       
  1185 
       
  1186         v = self._cooked.get(option)
       
  1187         if v is None:
       
  1188             v = self._raw.get(option)
       
  1189             if v is None:
       
  1190                 return default
       
  1191 
       
  1192         __doing__ = 'Getting option %s:%s.', self.name, option
       
  1193 
       
  1194         if '${' in v:
       
  1195             key = self.name, option
       
  1196             if seen is None:
       
  1197                 seen = [key]
       
  1198             elif key in seen:
       
  1199                 raise zc.buildout.UserError(
       
  1200                     "Circular reference in substitutions.\n"
       
  1201                     )
       
  1202             else:
       
  1203                 seen.append(key)
       
  1204             v = '$$'.join([self._sub(s, seen) for s in v.split('$$')])
       
  1205             seen.pop()
       
  1206 
       
  1207         self._data[option] = v
       
  1208         return v
       
  1209 
       
  1210     _template_split = re.compile('([$]{[^}]*})').split
       
  1211     _simple = re.compile('[-a-zA-Z0-9 ._]+$').match
       
  1212     _valid = re.compile('\${[-a-zA-Z0-9 ._]*:[-a-zA-Z0-9 ._]+}$').match
       
  1213     def _sub(self, template, seen):
       
  1214         value = self._template_split(template)
       
  1215         subs = []
       
  1216         for ref in value[1::2]:
       
  1217             s = tuple(ref[2:-1].split(':'))
       
  1218             if not self._valid(ref):
       
  1219                 if len(s) < 2:
       
  1220                     raise zc.buildout.UserError("The substitution, %s,\n"
       
  1221                                                 "doesn't contain a colon."
       
  1222                                                 % ref)
       
  1223                 if len(s) > 2:
       
  1224                     raise zc.buildout.UserError("The substitution, %s,\n"
       
  1225                                                 "has too many colons."
       
  1226                                                 % ref)
       
  1227                 if not self._simple(s[0]):
       
  1228                     raise zc.buildout.UserError(
       
  1229                         "The section name in substitution, %s,\n"
       
  1230                         "has invalid characters."
       
  1231                         % ref)
       
  1232                 if not self._simple(s[1]):
       
  1233                     raise zc.buildout.UserError(
       
  1234                         "The option name in substitution, %s,\n"
       
  1235                         "has invalid characters."
       
  1236                         % ref)
       
  1237 
       
  1238             section, option = s
       
  1239             if not section:
       
  1240                 section = self.name
       
  1241             v = self.buildout[section].get(option, None, seen)
       
  1242             if v is None:
       
  1243                 if option == '_buildout_section_name_':
       
  1244                     v = self.name
       
  1245                 else:
       
  1246                     raise MissingOption("Referenced option does not exist:",
       
  1247                                         section, option)
       
  1248             subs.append(v)
       
  1249         subs.append('')
       
  1250 
       
  1251         return ''.join([''.join(v) for v in zip(value[::2], subs)])
       
  1252 
       
  1253     def __getitem__(self, key):
       
  1254         try:
       
  1255             return self._data[key]
       
  1256         except KeyError:
       
  1257             pass
       
  1258 
       
  1259         v = self.get(key)
       
  1260         if v is None:
       
  1261             raise MissingOption("Missing option: %s:%s" % (self.name, key))
       
  1262         return v
       
  1263 
       
  1264     def __setitem__(self, option, value):
       
  1265         if not isinstance(value, str):
       
  1266             raise TypeError('Option values must be strings', value)
       
  1267         self._data[option] = value
       
  1268 
       
  1269     def __delitem__(self, key):
       
  1270         if key in self._raw:
       
  1271             del self._raw[key]
       
  1272             if key in self._data:
       
  1273                 del self._data[key]
       
  1274             if key in self._cooked:
       
  1275                 del self._cooked[key]
       
  1276         elif key in self._data:
       
  1277             del self._data[key]
       
  1278         else:
       
  1279             raise KeyError, key
       
  1280 
       
  1281     def keys(self):
       
  1282         raw = self._raw
       
  1283         return list(self._raw) + [k for k in self._data if k not in raw]
       
  1284 
       
  1285     def copy(self):
       
  1286         result = self._raw.copy()
       
  1287         result.update(self._cooked)
       
  1288         result.update(self._data)
       
  1289         return result
       
  1290 
       
  1291     def _call(self, f):
       
  1292         buildout_directory = self.buildout['buildout']['directory']
       
  1293         self._created = []
       
  1294         try:
       
  1295             try:
       
  1296                 os.chdir(buildout_directory)
       
  1297                 return f()
       
  1298             except:
       
  1299                 for p in self._created:
       
  1300                     if os.path.isdir(p):
       
  1301                         rmtree(p)
       
  1302                     elif os.path.isfile(p):
       
  1303                         os.remove(p)
       
  1304                     else:
       
  1305                         self.buildout._logger.warn("Couldn't clean up %r.", p)
       
  1306                 raise
       
  1307         finally:
       
  1308             self._created = None
       
  1309             os.chdir(buildout_directory)
       
  1310 
       
  1311     def created(self, *paths):
       
  1312         try:
       
  1313             self._created.extend(paths)
       
  1314         except AttributeError:
       
  1315             raise TypeError(
       
  1316                 "Attempt to register a created path while not installing",
       
  1317                 self.name)
       
  1318         return self._created
       
  1319 
       
  1320     def query_bool(self, name, default=None):
       
  1321         """Given a name, return a boolean value for that name.
       
  1322 
       
  1323         ``default``, if given, should be 'true', 'false', or None.
       
  1324         """
       
  1325         if default is not None:
       
  1326             value = self.setdefault(name, default=default)
       
  1327         else:
       
  1328             value = self.get(name)
       
  1329             if value is None:
       
  1330                 return value
       
  1331         return _convert_bool(name, value)
       
  1332 
       
  1333     def get_bool(self, name):
       
  1334         """Given a name, return a boolean value for that name.
       
  1335         """
       
  1336         return _convert_bool(name, self[name])
       
  1337 
       
  1338 
       
  1339 def _convert_bool(name, value):
       
  1340     if value not in ('true', 'false'):
       
  1341         raise zc.buildout.UserError(
       
  1342             'Invalid value for %s option: %s' % (name, value))
       
  1343     else:
       
  1344         return value == 'true'
       
  1345 
       
  1346 _spacey_nl = re.compile('[ \t\r\f\v]*\n[ \t\r\f\v\n]*'
       
  1347                         '|'
       
  1348                         '^[ \t\r\f\v]+'
       
  1349                         '|'
       
  1350                         '[ \t\r\f\v]+$'
       
  1351                         )
       
  1352 
       
  1353 _spacey_defaults = [
       
  1354     ('%(__buildout_space__)s',   ' '),
       
  1355     ('%(__buildout_space_n__)s', '\n'),
       
  1356     ('%(__buildout_space_r__)s', '\r'),
       
  1357     ('%(__buildout_space_f__)s', '\f'),
       
  1358     ('%(__buildout_space_v__)s', '\v'),
       
  1359     ]
       
  1360 
       
  1361 def _quote_spacey_nl(match):
       
  1362     match = match.group(0).split('\n', 1)
       
  1363     result = '\n\t'.join(
       
  1364         [(s
       
  1365           .replace(' ', '%(__buildout_space__)s')
       
  1366           .replace('\r', '%(__buildout_space_r__)s')
       
  1367           .replace('\f', '%(__buildout_space_f__)s')
       
  1368           .replace('\v', '%(__buildout_space_v__)s')
       
  1369           .replace('\n', '%(__buildout_space_n__)s')
       
  1370           )
       
  1371          for s in match]
       
  1372         )
       
  1373     return result
       
  1374 
       
  1375 def _save_option(option, value, f):
       
  1376     value = _spacey_nl.sub(_quote_spacey_nl, value)
       
  1377     if value.startswith('\n\t'):
       
  1378         value = '%(__buildout_space_n__)s' + value[2:]
       
  1379     if value.endswith('\n\t'):
       
  1380         value = value[:-2] + '%(__buildout_space_n__)s'
       
  1381     print >>f, option, '=', value
       
  1382 
       
  1383 def _save_options(section, options, f):
       
  1384     print >>f, '[%s]' % section
       
  1385     items = options.items()
       
  1386     items.sort()
       
  1387     for option, value in items:
       
  1388         _save_option(option, value, f)
       
  1389 
       
  1390 def _open(base, filename, seen, dl_options, override):
       
  1391     """Open a configuration file and return the result as a dictionary,
       
  1392 
       
  1393     Recursively open other files based on buildout options found.
       
  1394     """
       
  1395     _update_section(dl_options, override)
       
  1396     _dl_options = _unannotate_section(dl_options.copy())
       
  1397     is_temp = False
       
  1398     download = zc.buildout.download.Download(
       
  1399         _dl_options, cache=_dl_options.get('extends-cache'), fallback=True,
       
  1400         hash_name=True)
       
  1401     if _isurl(filename):
       
  1402         path, is_temp = download(filename)
       
  1403         fp = open(path)
       
  1404         base = filename[:filename.rfind('/')]
       
  1405     elif _isurl(base):
       
  1406         if os.path.isabs(filename):
       
  1407             fp = open(filename)
       
  1408             base = os.path.dirname(filename)
       
  1409         else:
       
  1410             filename = base + '/' + filename
       
  1411             path, is_temp = download(filename)
       
  1412             fp = open(path)
       
  1413             base = filename[:filename.rfind('/')]
       
  1414     else:
       
  1415         filename = os.path.join(base, filename)
       
  1416         fp = open(filename)
       
  1417         base = os.path.dirname(filename)
       
  1418 
       
  1419     if filename in seen:
       
  1420         if is_temp:
       
  1421             fp.close()
       
  1422             os.remove(path)
       
  1423         raise zc.buildout.UserError("Recursive file include", seen, filename)
       
  1424 
       
  1425     root_config_file = not seen
       
  1426     seen.append(filename)
       
  1427 
       
  1428     result = {}
       
  1429 
       
  1430     parser = ConfigParser.RawConfigParser()
       
  1431     parser.optionxform = lambda s: s
       
  1432     parser.readfp(fp)
       
  1433     if is_temp:
       
  1434         fp.close()
       
  1435         os.remove(path)
       
  1436 
       
  1437     extends = extended_by = None
       
  1438     for section in parser.sections():
       
  1439         options = dict(parser.items(section))
       
  1440         if section == 'buildout':
       
  1441             extends = options.pop('extends', extends)
       
  1442             extended_by = options.pop('extended-by', extended_by)
       
  1443         result[section] = options
       
  1444 
       
  1445     result = _annotate(result, filename)
       
  1446 
       
  1447     if root_config_file and 'buildout' in result:
       
  1448         dl_options = _update_section(dl_options, result['buildout'])
       
  1449 
       
  1450     if extends:
       
  1451         extends = extends.split()
       
  1452         eresult = _open(base, extends.pop(0), seen, dl_options, override)
       
  1453         for fname in extends:
       
  1454             _update(eresult, _open(base, fname, seen, dl_options, override))
       
  1455         result = _update(eresult, result)
       
  1456 
       
  1457     if extended_by:
       
  1458         self._logger.warn(
       
  1459             "The extendedBy option is deprecated.  Stop using it."
       
  1460             )
       
  1461         for fname in extended_by.split():
       
  1462             result = _update(result,
       
  1463                              _open(base, fname, seen, dl_options, override))
       
  1464 
       
  1465     seen.pop()
       
  1466     return result
       
  1467 
       
  1468 
       
  1469 ignore_directories = '.svn', 'CVS'
       
  1470 def _dir_hash(dir):
       
  1471     hash = md5()
       
  1472     for (dirpath, dirnames, filenames) in os.walk(dir):
       
  1473         dirnames[:] = [n for n in dirnames if n not in ignore_directories]
       
  1474         filenames[:] = [f for f in filenames
       
  1475                         if (not (f.endswith('pyc') or f.endswith('pyo'))
       
  1476                             and os.path.exists(os.path.join(dirpath, f)))
       
  1477                         ]
       
  1478         hash.update(' '.join(dirnames))
       
  1479         hash.update(' '.join(filenames))
       
  1480         for name in filenames:
       
  1481             hash.update(open(os.path.join(dirpath, name)).read())
       
  1482     return hash.digest().encode('base64').strip()
       
  1483 
       
  1484 def _dists_sig(dists):
       
  1485     result = []
       
  1486     for dist in dists:
       
  1487         location = dist.location
       
  1488         if dist.precedence == pkg_resources.DEVELOP_DIST:
       
  1489             result.append(dist.project_name + '-' + _dir_hash(location))
       
  1490         else:
       
  1491             result.append(os.path.basename(location))
       
  1492     return result
       
  1493 
       
  1494 def _update_section(s1, s2):
       
  1495     s2 = s2.copy() # avoid mutating the second argument, which is unexpected
       
  1496     for k, v in s2.items():
       
  1497         v2, note2 = v
       
  1498         if k.endswith('+'):
       
  1499             key = k.rstrip(' +')
       
  1500             v1, note1 = s1.get(key, ("", ""))
       
  1501             newnote = ' [+] '.join((note1, note2)).strip()
       
  1502             s2[key] = "\n".join((v1).split('\n') +
       
  1503                 v2.split('\n')), newnote
       
  1504             del s2[k]
       
  1505         elif k.endswith('-'):
       
  1506             key = k.rstrip(' -')
       
  1507             v1, note1 = s1.get(key, ("", ""))
       
  1508             newnote = ' [-] '.join((note1, note2)).strip()
       
  1509             s2[key] = ("\n".join(
       
  1510                 [v for v in v1.split('\n')
       
  1511                    if v not in v2.split('\n')]), newnote)
       
  1512             del s2[k]
       
  1513 
       
  1514     s1.update(s2)
       
  1515     return s1
       
  1516 
       
  1517 def _update(d1, d2):
       
  1518     for section in d2:
       
  1519         if section in d1:
       
  1520             d1[section] = _update_section(d1[section], d2[section])
       
  1521         else:
       
  1522             d1[section] = d2[section]
       
  1523     return d1
       
  1524 
       
  1525 def _recipe(options):
       
  1526     recipe = options['recipe']
       
  1527     if ':' in recipe:
       
  1528         recipe, entry = recipe.split(':')
       
  1529     else:
       
  1530         entry = 'default'
       
  1531 
       
  1532     return recipe, entry
       
  1533 
       
  1534 def _doing():
       
  1535     _, v, tb = sys.exc_info()
       
  1536     message = str(v)
       
  1537     doing = []
       
  1538     while tb is not None:
       
  1539         d = tb.tb_frame.f_locals.get('__doing__')
       
  1540         if d:
       
  1541             doing.append(d)
       
  1542         tb = tb.tb_next
       
  1543 
       
  1544     if doing:
       
  1545         sys.stderr.write('While:\n')
       
  1546         for d in doing:
       
  1547             if not isinstance(d, str):
       
  1548                 d = d[0] % d[1:]
       
  1549             sys.stderr.write('  %s\n' % d)
       
  1550 
       
  1551 def _error(*message):
       
  1552     sys.stderr.write('Error: ' + ' '.join(message) +'\n')
       
  1553     sys.exit(1)
       
  1554 
       
  1555 _internal_error_template = """
       
  1556 An internal error occurred due to a bug in either zc.buildout or in a
       
  1557 recipe being used:
       
  1558 """
       
  1559 
       
  1560 def _check_for_unused_options_in_section(buildout, section):
       
  1561     options = buildout[section]
       
  1562     unused = [option for option in options._raw if option not in options._data]
       
  1563     if unused:
       
  1564         buildout._logger.warn("Unused options for %s: %s."
       
  1565                               % (section, ' '.join(map(repr, unused)))
       
  1566                               )
       
  1567 
       
  1568 _early_release_initialization_code = """\
       
  1569 sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true')
       
  1570 print ('NOTE: Accepting early releases of build system packages.  Rerun '
       
  1571        'bootstrap without --accept-buildout-test-releases (-t) to return to '
       
  1572        'default behavior.')
       
  1573 """
       
  1574 
       
  1575 _usage = """\
       
  1576 Usage: buildout [options] [assignments] [command [command arguments]]
       
  1577 
       
  1578 Options:
       
  1579 
       
  1580   -h, --help
       
  1581 
       
  1582      Print this message and exit.
       
  1583 
       
  1584   -v
       
  1585 
       
  1586      Increase the level of verbosity.  This option can be used multiple times.
       
  1587 
       
  1588   -q
       
  1589 
       
  1590      Decrease the level of verbosity.  This option can be used multiple times.
       
  1591 
       
  1592   -c config_file
       
  1593 
       
  1594      Specify the path to the buildout configuration file to be used.
       
  1595      This defaults to the file named "buildout.cfg" in the current
       
  1596      working directory.
       
  1597 
       
  1598   -t socket_timeout
       
  1599 
       
  1600      Specify the socket timeout in seconds.
       
  1601 
       
  1602   -U
       
  1603 
       
  1604      Don't read user defaults.
       
  1605 
       
  1606   -o
       
  1607 
       
  1608     Run in off-line mode.  This is equivalent to the assignment
       
  1609     buildout:offline=true.
       
  1610 
       
  1611   -O
       
  1612 
       
  1613     Run in non-off-line mode.  This is equivalent to the assignment
       
  1614     buildout:offline=false.  This is the default buildout mode.  The
       
  1615     -O option would normally be used to override a true offline
       
  1616     setting in a configuration file.
       
  1617 
       
  1618   -n
       
  1619 
       
  1620     Run in newest mode.  This is equivalent to the assignment
       
  1621     buildout:newest=true.  With this setting, which is the default,
       
  1622     buildout will try to find the newest versions of distributions
       
  1623     available that satisfy its requirements.
       
  1624 
       
  1625   -N
       
  1626 
       
  1627     Run in non-newest mode.  This is equivalent to the assignment
       
  1628     buildout:newest=false.  With this setting, buildout will not seek
       
  1629     new distributions if installed distributions satisfy it's
       
  1630     requirements.
       
  1631 
       
  1632   -D
       
  1633 
       
  1634     Debug errors.  If an error occurs, then the post-mortem debugger
       
  1635     will be started. This is especially useful for debuging recipe
       
  1636     problems.
       
  1637 
       
  1638   -s
       
  1639 
       
  1640     Squelch warnings about using an executable with a broken -S
       
  1641     implementation.
       
  1642 
       
  1643 Assignments are of the form: section:option=value and are used to
       
  1644 provide configuration options that override those given in the
       
  1645 configuration file.  For example, to run the buildout in offline mode,
       
  1646 use buildout:offline=true.
       
  1647 
       
  1648 Options and assignments can be interspersed.
       
  1649 
       
  1650 Commands:
       
  1651 
       
  1652   install [parts]
       
  1653 
       
  1654     Install parts.  If no command arguments are given, then the parts
       
  1655     definition from the configuration file is used.  Otherwise, the
       
  1656     arguments specify the parts to be installed.
       
  1657 
       
  1658     Note that the semantics differ depending on whether any parts are
       
  1659     specified.  If parts are specified, then only those parts will be
       
  1660     installed. If no parts are specified, then the parts specified by
       
  1661     the buildout parts option will be installed along with all of
       
  1662     their dependencies.
       
  1663 
       
  1664   bootstrap
       
  1665 
       
  1666     Create a new buildout in the current working directory, copying
       
  1667     the buildout and setuptools eggs and, creating a basic directory
       
  1668     structure and a buildout-local buildout script.
       
  1669 
       
  1670   init
       
  1671 
       
  1672     Initialize a buildout, creating a buildout.cfg file if it doesn't
       
  1673     exist and then performing the same actions as for the buildout
       
  1674     command.
       
  1675 
       
  1676   setup script [setup command and options]
       
  1677 
       
  1678     Run a given setup script arranging that setuptools is in the
       
  1679     script's path and and that it has been imported so that
       
  1680     setuptools-provided commands (like bdist_egg) can be used even if
       
  1681     the setup script doesn't import setuptools itself.
       
  1682 
       
  1683     The script can be given either as a script path or a path to a
       
  1684     directory containing a setup.py script.
       
  1685 
       
  1686   annotate
       
  1687 
       
  1688     Display annotated sections. All sections are displayed, sorted
       
  1689     alphabetically. For each section, all key-value pairs are displayed,
       
  1690     sorted alphabetically, along with the origin of the value (file name or
       
  1691     COMPUTED_VALUE, DEFAULT_VALUE, COMMAND_LINE_VALUE).
       
  1692 
       
  1693 """
       
  1694 def _help():
       
  1695     print _usage
       
  1696     sys.exit(0)
       
  1697 
       
  1698 def main(args=None):
       
  1699     if args is None:
       
  1700         args = sys.argv[1:]
       
  1701 
       
  1702     config_file = 'buildout.cfg'
       
  1703     verbosity = 0
       
  1704     options = []
       
  1705     windows_restart = False
       
  1706     user_defaults = True
       
  1707     debug = False
       
  1708     ignore_broken_dash_s = False
       
  1709     while args:
       
  1710         if args[0][0] == '-':
       
  1711             op = orig_op = args.pop(0)
       
  1712             op = op[1:]
       
  1713             while op and op[0] in 'vqhWUoOnNDAs':
       
  1714                 if op[0] == 'v':
       
  1715                     verbosity += 10
       
  1716                 elif op[0] == 'q':
       
  1717                     verbosity -= 10
       
  1718                 elif op[0] == 'W':
       
  1719                     windows_restart = True
       
  1720                 elif op[0] == 'U':
       
  1721                     user_defaults = False
       
  1722                 elif op[0] == 'o':
       
  1723                     options.append(('buildout', 'offline', 'true'))
       
  1724                 elif op[0] == 'O':
       
  1725                     options.append(('buildout', 'offline', 'false'))
       
  1726                 elif op[0] == 'n':
       
  1727                     options.append(('buildout', 'newest', 'true'))
       
  1728                 elif op[0] == 'N':
       
  1729                     options.append(('buildout', 'newest', 'false'))
       
  1730                 elif op[0] == 'D':
       
  1731                     debug = True
       
  1732                 elif op[0] == 's':
       
  1733                     ignore_broken_dash_s = True
       
  1734                 else:
       
  1735                     _help()
       
  1736                 op = op[1:]
       
  1737 
       
  1738             if op[:1] in  ('c', 't'):
       
  1739                 op_ = op[:1]
       
  1740                 op = op[1:]
       
  1741 
       
  1742                 if op_ == 'c':
       
  1743                     if op:
       
  1744                         config_file = op
       
  1745                     else:
       
  1746                         if args:
       
  1747                             config_file = args.pop(0)
       
  1748                         else:
       
  1749                             _error("No file name specified for option", orig_op)
       
  1750                 elif op_ == 't':
       
  1751                     try:
       
  1752                         timeout = int(args.pop(0))
       
  1753                     except IndexError:
       
  1754                         _error("No timeout value specified for option", orig_op)
       
  1755                     except ValueError:
       
  1756                         _error("No timeout value must be numeric", orig_op)
       
  1757 
       
  1758                     import socket
       
  1759                     print 'Setting socket time out to %d seconds' % timeout
       
  1760                     socket.setdefaulttimeout(timeout)
       
  1761 
       
  1762             elif op:
       
  1763                 if orig_op == '--help':
       
  1764                     _help()
       
  1765                 _error("Invalid option", '-'+op[0])
       
  1766         elif '=' in args[0]:
       
  1767             option, value = args.pop(0).split('=', 1)
       
  1768             if len(option.split(':')) != 2:
       
  1769                 _error('Invalid option:', option)
       
  1770             section, option = option.split(':')
       
  1771             options.append((section.strip(), option.strip(), value.strip()))
       
  1772         else:
       
  1773             # We've run out of command-line options and option assignnemnts
       
  1774             # The rest should be commands, so we'll stop here
       
  1775             break
       
  1776 
       
  1777     if verbosity < 0 or ignore_broken_dash_s:
       
  1778         broken_dash_S_filter_action = 'ignore'
       
  1779     elif verbosity == 0: # This is the default.
       
  1780         broken_dash_S_filter_action = 'once'
       
  1781     else:
       
  1782         broken_dash_S_filter_action = 'default'
       
  1783     warnings.filterwarnings(
       
  1784         broken_dash_S_filter_action,
       
  1785         re.escape(
       
  1786             zc.buildout.easy_install.BROKEN_DASH_S_WARNING),
       
  1787         UserWarning)
       
  1788     if verbosity:
       
  1789         options.append(('buildout', 'verbosity', str(verbosity)))
       
  1790 
       
  1791     if args:
       
  1792         command = args.pop(0)
       
  1793         if command not in (
       
  1794             'install', 'bootstrap', 'runsetup', 'setup', 'init',
       
  1795             'annotate',
       
  1796             ):
       
  1797             _error('invalid command:', command)
       
  1798     else:
       
  1799         command = 'install'
       
  1800 
       
  1801     try:
       
  1802         try:
       
  1803             buildout = Buildout(config_file, options,
       
  1804                                 user_defaults, windows_restart, command)
       
  1805             getattr(buildout, command)(args)
       
  1806         except SystemExit:
       
  1807             pass
       
  1808         except Exception, v:
       
  1809             _doing()
       
  1810             exc_info = sys.exc_info()
       
  1811             import pdb, traceback
       
  1812             if debug:
       
  1813                 traceback.print_exception(*exc_info)
       
  1814                 sys.stderr.write('\nStarting pdb:\n')
       
  1815                 pdb.post_mortem(exc_info[2])
       
  1816             else:
       
  1817                 if isinstance(v, (zc.buildout.UserError,
       
  1818                                   distutils.errors.DistutilsError,
       
  1819                                   )
       
  1820                               ):
       
  1821                     _error(str(v))
       
  1822                 else:
       
  1823                     sys.stderr.write(_internal_error_template)
       
  1824                     traceback.print_exception(*exc_info)
       
  1825                     sys.exit(1)
       
  1826 
       
  1827 
       
  1828     finally:
       
  1829         logging.shutdown()
       
  1830 
       
  1831 if sys.version_info[:2] < (2, 4):
       
  1832     def reversed(iterable):
       
  1833         result = list(iterable);
       
  1834         result.reverse()
       
  1835         return result