[Checkins] SVN: zc.buildout/trunk/ Added an upload entry point for extensions.

Jim Fulton jim at zope.com
Fri Jun 19 16:56:54 EDT 2009


Log message for revision 101154:
  Added an upload entry point for extensions.
  
  Also fixed some spurious failures in the bootstrap test.
  

Changed:
  U   zc.buildout/trunk/CHANGES.txt
  U   zc.buildout/trunk/src/zc/buildout/bootstrap.txt
  U   zc.buildout/trunk/src/zc/buildout/buildout.py
  U   zc.buildout/trunk/src/zc/buildout/buildout.txt
  U   zc.buildout/trunk/src/zc/buildout/tests.py

-=-
Modified: zc.buildout/trunk/CHANGES.txt
===================================================================
--- zc.buildout/trunk/CHANGES.txt	2009-06-19 20:40:56 UTC (rev 101153)
+++ zc.buildout/trunk/CHANGES.txt	2009-06-19 20:56:53 UTC (rev 101154)
@@ -1,7 +1,7 @@
 Change History
 **************
 
-1.2.2 (unreleased)
+1.2.2 (2009-06-19)
 ==================
 
 - Better Windows compatibility in test infrastructure.
@@ -16,7 +16,9 @@
 
 - fixed usage of 'relative_paths' keyword parameter on Windows
 
+- Added an unload entry point for extensions.
 
+
 1.2.1 (2009-03-18)
 ==================
 

Modified: zc.buildout/trunk/src/zc/buildout/bootstrap.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/bootstrap.txt	2009-06-19 20:40:56 UTC (rev 101153)
+++ zc.buildout/trunk/src/zc/buildout/bootstrap.txt	2009-06-19 20:56:53 UTC (rev 101154)
@@ -59,12 +59,7 @@
     X
     No local packages or download links found for zc.buildout==UNKNOWN
     error: Could not find suitable distribution for Requirement.parse('zc.buildout==UNKNOWN')
-    Traceback (most recent call last):
-      File "bootstrap.py", line 78, in <module>
-        ) == 0
-    AssertionError
-    <BLANKLINE>
-    X
+    ...
 
 Now let's try with `1.1.2`, which happens to exist::
 

Modified: zc.buildout/trunk/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.py	2009-06-19 20:40:56 UTC (rev 101153)
+++ zc.buildout/trunk/src/zc/buildout/buildout.py	2009-06-19 20:56:53 UTC (rev 101154)
@@ -83,7 +83,7 @@
                  user_defaults=True, windows_restart=False, command=None):
 
         __doing__ = 'Initializing.'
-        
+
         self.__windows_restart = windows_restart
 
         # default options
@@ -138,7 +138,7 @@
         # because while parsing options those attributes might be
         # used already (Gottfried Ganssauge)
         buildout_section = data.get('buildout')
-            
+
         # Try to make sure we have absolute paths for standard
         # directories. We do this before doing substitutions, in case
         # a one of these gets read by another section.  If any
@@ -155,13 +155,13 @@
 
         allow_hosts = buildout_section and buildout_section.get(
              'allow-hosts', '*').split('\n')
-        self._allow_hosts = tuple([host.strip() for host in allow_hosts 
+        self._allow_hosts = tuple([host.strip() for host in allow_hosts
                                    if host.strip() != ''])
 
         self._logger = logging.getLogger('zc.buildout')
         self.offline = False
         self.newest = True
-        
+
         ##################################################################
         ## WARNING!!!
         ## ALL ATTRIBUTES MUST HAVE REASONABLE DEFAULTS AT THIS POINT
@@ -173,9 +173,9 @@
         # now reinitialize
         links = options.get('find-links', '')
         self._links = links and links.split() or ()
-        
+
         allow_hosts = options.get('allow-hosts', '*').split('\n')
-        self._allow_hosts = tuple([host.strip() for host in allow_hosts 
+        self._allow_hosts = tuple([host.strip() for host in allow_hosts
                                    if host.strip() != ''])
 
         self._buildout_dir = options['directory']
@@ -216,7 +216,7 @@
             self._error('Invalid value for prefer-final option: %s',
                         prefer_final)
         zc.buildout.easy_install.prefer_final(prefer_final=='true')
-        
+
         use_dependency_links = options.get('use-dependency-links', 'true')
         if use_dependency_links not in ('true', 'false'):
             self._error('Invalid value for use-dependency-links option: %s',
@@ -243,7 +243,7 @@
             download_cache = os.path.join(download_cache, 'dist')
             if not os.path.isdir(download_cache):
                 os.mkdir(download_cache)
-                
+
             zc.buildout.easy_install.download_cache(download_cache)
 
         install_from_cache = options.get('install-from-cache')
@@ -335,7 +335,7 @@
         installed_develop_eggs = self._develop()
         installed_part_options['buildout']['installed_develop_eggs'
                                            ] = installed_develop_eggs
-        
+
         if installed_exists:
             self._update_installed(
                 installed_develop_eggs=installed_develop_eggs)
@@ -345,7 +345,7 @@
         conf_parts = conf_parts and conf_parts.split() or []
         installed_parts = installed_part_options['buildout']['parts']
         installed_parts = installed_parts and installed_parts.split() or []
-        
+
         if install_args:
             install_parts = install_args
             uninstall_missing = False
@@ -361,11 +361,11 @@
         if self._log_level < logging.DEBUG:
             sections = list(self)
             sections.sort()
-            print    
+            print
             print 'Configuration data:'
             for section in self._data:
                 _save_options(section, self[section], sys.stdout)
-            print    
+            print
 
 
         # compute new part recipe signatures
@@ -493,7 +493,7 @@
 
             if need_to_save_installed:
                 installed_part_options['buildout']['parts'] = (
-                    ' '.join(installed_parts))            
+                    ' '.join(installed_parts))
                 self._save_installed_options(installed_part_options)
                 installed_exists = True
             else:
@@ -506,6 +506,8 @@
         elif (not installed_parts) and installed_exists:
             os.remove(self['buildout']['installed'])
 
+        self._unload_extensions()
+
     def _update_installed(self, **buildout_options):
         installed = self['buildout']['installed']
         f = open(installed, 'a')
@@ -533,7 +535,6 @@
         self._uninstall(
             installed_part_options[part]['__buildout_installed__'])
 
-
     def _setup_directories(self):
         __doing__ = 'Setting up buildout directories'
 
@@ -564,7 +565,8 @@
                     setup = self._buildout_path(setup)
                     files = glob.glob(setup)
                     if not files:
-                        self._logger.warn("Couldn't develop %r (not found)", setup)
+                        self._logger.warn("Couldn't develop %r (not found)",
+                                          setup)
                     else:
                         files.sort()
                     for setup in files:
@@ -581,7 +583,7 @@
                      if f not in old_files
                      ]))
                 raise
-                     
+
             else:
                 self._sanity_check_develop_eggs_files(dest, old_files)
                 return '\n'.join([os.path.join(dest, f)
@@ -628,7 +630,7 @@
                             value = value.replace(k, v)
                     options[option] = value
                 result[section] = Options(self, section, options)
-                        
+
             return result, True
         else:
             return ({'buildout': Options(self, 'buildout', {'parts': ''})},
@@ -656,8 +658,8 @@
                         # Sigh. This is the exectable used to run the buildout
                         # and, of course, it's in use. Leave it.
                         ):
-                        raise                    
-                
+                        raise
+
     def _install(self, part):
         options = self[part]
         recipe, entry = _recipe(options)
@@ -701,7 +703,7 @@
             buildout_handler.setFormatter(logging.Formatter('%(message)s'))
             self._logger.propagate = False
             self._logger.addHandler(buildout_handler)
-            
+
         handler.setFormatter(logging.Formatter(log_format))
         root_logger.addHandler(handler)
 
@@ -730,7 +732,7 @@
 
         if not self.newest:
             return
-        
+
         ws = zc.buildout.easy_install.install(
             [
             (spec + ' ' + self['buildout'].get(spec+'-version', '')).strip()
@@ -774,8 +776,8 @@
             if not __debug__:
                 args.insert(0, '-O')
             args.insert(0, zc.buildout.easy_install._safe_arg (sys.executable))
-            os.execv(sys.executable, args)            
-        
+            os.execv(sys.executable, args)
+
         self._logger.info("Upgraded:\n  %s;\nrestarting.",
                           ",\n  ".join([("%s version %s"
                                        % (dist.project_name, dist.version)
@@ -784,7 +786,7 @@
                                       ]
                                      ),
                           )
-                
+
         # the new dist is different, so we've upgraded.
         # Update the scripts and return True
         zc.buildout.easy_install.scripts(
@@ -831,6 +833,14 @@
             for ep in pkg_resources.iter_entry_points('zc.buildout.extension'):
                 ep.load()(self)
 
+    def _unload_extensions(self):
+        __doing__ = 'Unloading extensions.'
+        specs = self['buildout'].get('extensions', '').split()
+        if specs:
+            for ep in pkg_resources.iter_entry_points(
+                'zc.buildout.unloadextension'):
+                ep.load()(self)
+
     def setup(self, args):
         if not args:
             raise zc.buildout.UserError(
@@ -854,13 +864,13 @@
                 ))
             if is_jython:
                 arg_list = list()
-                
+
                 for a in args:
                     add_args.append(zc.buildout.easy_install._safe_arg(a))
-                
+
                 subprocess.Popen([zc.buildout.easy_install._safe_arg(sys.executable)] + list(tsetup) +
                                 arg_list).wait()
-            
+
             else:
                 os.spawnl(os.P_WAIT, sys.executable, zc.buildout.easy_install._safe_arg (sys.executable), tsetup,
                         *[zc.buildout.easy_install._safe_arg(a)
@@ -886,7 +896,7 @@
         options = Options(self, section, data)
         self._data[section] = options
         options._initialize()
-        return options          
+        return options
 
     def __setitem__(self, key, value):
         raise NotImplementedError('__setitem__')
@@ -951,7 +961,7 @@
     def _initialize(self):
         name = self.name
         __doing__ = 'Initializing section %s.', name
-        
+
         # force substitutions
         for k, v in self._raw.items():
             if '${' in v:
@@ -959,11 +969,11 @@
 
         if self.name == 'buildout':
             return # buildout section can never be a part
-        
+
         recipe = self.get('recipe')
         if not recipe:
             return
-        
+
         reqs, entry = _recipe(self._data)
         buildout = self.buildout
         recipe_class = _install_and_load(reqs, 'zc.buildout', entry, buildout)
@@ -1035,7 +1045,7 @@
                         "The option name in substitution, %s,\n"
                         "has invalid characters."
                         % ref)
-                
+
             v = self.buildout[s[0]].get(s[1], None, seen)
             if v is None:
                 raise MissingOption("Referenced option does not exist:", *s)
@@ -1043,7 +1053,7 @@
         subs.append('')
 
         return ''.join([''.join(v) for v in zip(value[::2], subs)])
-        
+
     def __getitem__(self, key):
         try:
             return self._data[key]
@@ -1147,7 +1157,7 @@
     if value.endswith('\n\t'):
         value = value[:-2] + '%(__buildout_space_n__)s'
     print >>f, option, '=', value
-    
+
 def _save_options(section, options, f):
     print >>f, '[%s]' % section
     items = options.items()
@@ -1210,8 +1220,8 @@
 
     seen.pop()
     return result
-    
 
+
 ignore_directories = '.svn', 'CVS'
 def _dir_hash(dir):
     hash = md5()
@@ -1226,7 +1236,7 @@
         for name in filenames:
             hash.update(open(os.path.join(dirpath, name)).read())
     return hash.digest().encode('base64').strip()
-    
+
 def _dists_sig(dists):
     result = []
     for dist in dists:
@@ -1248,7 +1258,7 @@
             s2[key] = "\n".join([v for v in s1.get(key, "").split('\n')
                                  if v not in s2[k].split('\n')])
             del s2[k]
-                
+
     s1.update(s2)
     return s1
 
@@ -1278,7 +1288,7 @@
         if d:
             doing.append(d)
         tb = tb.tb_next
-        
+
     if doing:
         sys.stderr.write('While:\n')
         for d in doing:
@@ -1335,13 +1345,13 @@
      Don't read user defaults.
 
   -o
-  
-    Run in off-line mode.  This is equivalent to the assignment 
+
+    Run in off-line mode.  This is equivalent to the assignment
     buildout:offline=true.
 
   -O
 
-    Run in non-off-line mode.  This is equivalent to the assignment 
+    Run in non-off-line mode.  This is equivalent to the assignment
     buildout:offline=false.  This is the default buildout mode.  The
     -O option would normally be used to override a true offline
     setting in a configuration file.
@@ -1355,10 +1365,10 @@
 
   -N
 
-    Run in non-newest mode.  This is equivalent to the assignment 
+    Run in non-newest mode.  This is equivalent to the assignment
     buildout:newest=false.  With this setting, buildout will not seek
     new distributions if installed distributions satisfy it's
-    requirements. 
+    requirements.
 
   -D
 
@@ -1408,7 +1418,7 @@
 
     The script can be given either as a script path or a path to a
     directory containing a setup.py script.
-    
+
 """
 def _help():
     print _usage
@@ -1450,7 +1460,7 @@
                 else:
                     _help()
                 op = op[1:]
-                
+
             if op[:1] in  ('c', 't'):
                 op_ = op[:1]
                 op = op[1:]
@@ -1527,8 +1537,8 @@
                     sys.stderr.write(_internal_error_template)
                     traceback.print_exception(*exc_info)
                     sys.exit(1)
-    
-            
+
+
     finally:
             logging.shutdown()
 

Modified: zc.buildout/trunk/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.txt	2009-06-19 20:40:56 UTC (rev 101153)
+++ zc.buildout/trunk/src/zc/buildout/buildout.txt	2009-06-19 20:56:53 UTC (rev 101154)
@@ -2368,15 +2368,17 @@
 Extensions
 ----------
 
-An **experimental** feature allows code to be loaded and run after
+A feature allows code to be loaded and run after
 configuration files have been read but before the buildout has begun
 any processing.  The intent is to allow special plugins such as
 urllib2 request handlers to be loaded.
 
 To load an extension, we use the extensions option and list one or
 more distribution requirements, on separate lines.  The distributions
-named will be loaded and any zc.buildout.extensions entry points found
-will be called with the buildout as an argument.
+named will be loaded and any ``zc.buildout.extension`` entry points found
+will be called with the buildout as an argument.  When buildout
+finishes processing, any ``zc.buildout.unloadextension`` entry points
+found will be called with the buildout as an argument.
 
 Let's create a sample extension in our sample buildout created in the
 previous section:
@@ -2387,6 +2389,8 @@
     ... """
     ... def ext(buildout):
     ...     print 'ext', list(buildout)
+    ... def unload(buildout):
+    ...     print 'unload', list(buildout)
     ... """)
 
     >>> write(sample_bootstrapped, 'demo', 'setup.py',
@@ -2395,7 +2399,10 @@
     ...
     ... setup(
     ...     name = "demo",
-    ...     entry_points = {'zc.buildout.extension': ['ext = demo:ext']},
+    ...     entry_points = {
+    ...        'zc.buildout.extension': ['ext = demo:ext'],
+    ...        'zc.buildout.unloadextension': ['ext = demo:unload'],
+    ...        },
     ...     )
     ... """)
 
@@ -2436,6 +2443,7 @@
     >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')),
     ext ['buildout']
     Develop: '/sample-bootstrapped/demo'
+    unload ['buildout']
 
 Allow hosts
 -----------

Modified: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py	2009-06-19 20:40:56 UTC (rev 101153)
+++ zc.buildout/trunk/src/zc/buildout/tests.py	2009-06-19 20:56:53 UTC (rev 101154)
@@ -2895,6 +2895,7 @@
                zc.buildout.testing.normalize_endings,
                zc.buildout.testing.normalize_script,
                normalize_bang,
+               (re.compile('Downloading.*setuptools.*egg\n'), ''),
                ]),
             ))
 



More information about the Checkins mailing list