[cig-commits] r5238 - in cs/merlin/trunk: . merlin merlin/archimedes merlin/command merlin.egg-info

leif at geodynamics.org leif at geodynamics.org
Fri Nov 10 16:17:43 PST 2006


Author: leif
Date: 2006-11-10 16:17:42 -0800 (Fri, 10 Nov 2006)
New Revision: 5238

Added:
   cs/merlin/trunk/merlin/archimedes/
   cs/merlin/trunk/merlin/archimedes/__init__.py
Modified:
   cs/merlin/trunk/merlin.egg-info/PKG-INFO
   cs/merlin/trunk/merlin.egg-info/SOURCES.txt
   cs/merlin/trunk/merlin.egg-info/entry_points.txt
   cs/merlin/trunk/merlin/__init__.py
   cs/merlin/trunk/merlin/command/easy_install.py
   cs/merlin/trunk/merlin/dist.py
   cs/merlin/trunk/setup.py
Log:
Added bootstrapping mechanism ('archimedes').  Unlike ez_setup,
archimedes always downloads the most recent version of Merlin
along the required branch, and it doesn't bother with all that
silly MD5 stuff.


Modified: cs/merlin/trunk/merlin/__init__.py
===================================================================
--- cs/merlin/trunk/merlin/__init__.py	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin/__init__.py	2006-11-11 00:17:42 UTC (rev 5238)
@@ -76,15 +76,63 @@
 distutils.core.Command = Command    # we can't patch distutils.cmd, alas
 
 
+def main(argv=None, **kw):
+    import sys
+    import distutils.core
 
+    USAGE = """\
+usage: %(script)s [options] requirement_or_url ...
+   or: %(script)s --help
+"""
 
+    def gen_usage (script_name):
+        script = os.path.basename(script_name)
+        return USAGE % vars()
 
+    def with_ei_usage(f):
+        old_gen_usage = distutils.core.gen_usage
+        try:
+            distutils.core.gen_usage = gen_usage
+            return f()
+        finally:
+            distutils.core.gen_usage = old_gen_usage
 
+    class DistributionWithoutHelpCommands(Distribution):
+        def _show_help(self,*args,**kw):
+            with_ei_usage(lambda: Distribution._show_help(self,*args,**kw))
 
+    if argv is None:
+        argv = sys.argv[1:]
 
+    def usage():
+        print >> sys.stderr, "Usage: merlin [merlin-options] <command> [command-options-and-arguments]"
+        sys.exit(1)
 
+    def help():
+        # NYI
+        usage()
 
+    def install():
+        with_ei_usage(lambda:
+            setup(
+                script_args = ['-q','easy_install', '-v']+argv,
+                script_name = sys.argv[0] or 'easy_install',
+                distclass=DistributionWithoutHelpCommands, **kw
+            )
+        )
+    
+    if not argv:
+        usage()
 
+    command = argv.pop(0)
+    if command == 'help':
+        help()
+    elif command == 'install':
+        install()
+    else:
+        usage()
+    
+    return
 
 
 
@@ -92,6 +140,20 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 """Package resource API
 --------------------
 

Copied: cs/merlin/trunk/merlin/archimedes/__init__.py (from rev 5235, cs/merlin/trunk/ez_setup.py)
===================================================================
--- cs/merlin/trunk/ez_setup.py	2006-11-10 19:20:56 UTC (rev 5235)
+++ cs/merlin/trunk/merlin/archimedes/__init__.py	2006-11-11 00:17:42 UTC (rev 5238)
@@ -0,0 +1,181 @@
+#!python
+"""Bootstrap merlin installation
+
+If you want to use merlin in your package's setup.py, just include
+this directory as a subdirectory alongside setup.py (using
+svn:externals), and add this to the top of your setup.py::
+
+    from archimedes import use_merlin
+    use_merlin()
+
+If you want to require a specific version of merlin, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_merlin()``.
+
+This file can also be run as a script to install or upgrade merlin.
+"""
+
+import sys, os
+
+# Create a new branch of the Merlin project when introducing
+# backwards-incompatible changes.  Adjust the following numbers when
+# creating a branch.  Branch numbers follow the CVS convention (but
+# with no even/odd rules).
+
+branch          = "1"
+endOfBranch     = "2a"
+default_url     = "http://cheeseshop.python.org/packages/any/m/merlin/"
+reqSpec         = "merlin >= %s, < %s" % (branch, endOfBranch)
+
+def use_merlin(package_index=default_url, to_dir=os.curdir, download_delay=15):
+    """Automatically find/download merlin and make it available on sys.path
+
+    `package_index` is a URL (ending with a '/') which contains merlin
+    eggs.  `to_dir` is the directory where merlin will be downloaded,
+    if it is not already available.  If `download_delay` is specified,
+    it should be the number of seconds that will be paused before
+    initiating a download, should one be required.  If an older
+    version of merlin is installed, this routine will print a message
+    to ``sys.stderr`` and raise SystemExit in an attempt to abort the
+    calling script.
+    """
+    try:
+        import merlin
+    except ImportError:
+        egg = download_merlin(package_index, to_dir, download_delay)
+        sys.path.insert(0, egg)
+        import merlin; merlin.bootstrap_install_from = egg
+
+    try:
+        merlin.require(reqSpec)
+
+    except merlin.VersionConflict, e:
+        # XXX could we install in a subprocess here?
+        print >>sys.stderr, (
+            "The required version of merlin (v%s) is not available, and\n"
+            "can't be installed while this script is running. Please install\n"
+            " a more recent version first.\n\n(Currently using %r)"
+        ) % (branch, e.args[0])
+        sys.exit(2)
+
+def download_merlin(package_index=default_url, to_dir=os.curdir, delay=15):
+    """Download merlin from a specified location and return its filename
+
+    `package_index` is a URL (ending with a '/') which contains merlin
+    eggs. `to_dir` is the directory where the egg will be downloaded.
+    `delay` is the number of seconds to pause before an actual
+    download attempt.
+    """
+    import urllib2, urlparse, shutil, re
+    from glob import glob
+    
+    # Avoid repeated downloads
+    candidates = []
+    candidateMap = {}
+    for egg in glob(os.path.join(to_dir, "*.egg")):
+        basename = os.path.basename(egg)
+        name, version = basename[:-4].split('-')
+        if name == "merlin" and version.startswith(branch + "."):
+            candidates.append(basename)
+            candidateMap[basename] = egg
+    
+    if candidates:
+        candidates.sort()
+        winner = candidates[-1]
+        saveto = candidateMap[winner]
+    else:
+        src = dst = None
+        try:
+            from distutils import log
+            if delay:
+                log.warn("""
+---------------------------------------------------------------------------
+This script requires merlin version %s to run (even to display
+help).  I will attempt to download it for you (from
+%s), but
+you may need to enable firewall access for this script first.
+I will start the download in %d seconds.
+
+(Note: if this machine does not have network access, please obtain the
+most recent version of merlin v%s and place it in this directory
+before rerunning this script.)
+---------------------------------------------------------------------------""",
+                    branch, package_index, delay, branch
+                ); from time import sleep; sleep(delay)
+
+            # scan the package index
+            candidates = []
+            candidateMap = {}
+            log.warn("Scanning %s", package_index)
+            src = urllib2.urlopen(package_index)
+            base = src.url     # handle redirects
+            data = src.read()
+            HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
+            # this is here to fix emacs' cruddy broken syntax highlighting
+            for match in HREF.finditer(data):
+                link = urlparse.urljoin(base, match.group(1))
+                scheme, server, path, parameters, query, fragment = urlparse.urlparse(link)
+                basename = urllib2.unquote(path.split('/')[-1])
+                if '#' in basename: basename, fragment = basename.split('#',1)
+                if basename.endswith('.egg') and '-' in basename:
+                    name, version = basename[:-4].split('-')
+                    if name == "merlin" and version.startswith(branch + "."):
+                        candidates.append(basename)
+                        candidateMap[basename] = link
+
+            if not candidates:
+                print >>sys.stderr, (
+                    "The required version of merlin (v%s) cannot be found.\n"
+                    ) % branch
+                sys.exit(3)
+            
+            candidates.sort()
+            winner = candidates[-1]
+            url = candidateMap[winner]
+            saveto = os.path.join(to_dir, winner)
+            
+            log.warn("Downloading %s", url)
+            src = urllib2.urlopen(url)
+            # Read/write all in one block, so we don't create a corrupt file
+            # if the download is interrupted.
+            data = src.read()
+            dst = open(saveto,"wb"); dst.write(data)
+        finally:
+            if src: src.close()
+            if dst: dst.close()
+    return os.path.realpath(saveto)
+
+def main(argv):
+    """Install or upgrade merlin"""
+
+    try:
+        import merlin
+    except ImportError:
+        egg = None
+        try:
+            egg = download_merlin(delay=0)
+            sys.path.insert(0,egg)
+            from merlin import main
+            return main(['install'] + list(argv) + [egg])   # we're done here
+        finally:
+            if egg and os.path.exists(egg):
+                os.unlink(egg)
+
+    import merlin
+    try:
+        merlin.require(reqSpec)
+    except merlin.VersionConflict:
+        from merlin import main
+        main(list(argv)+[download_merlin(delay=0)])
+        sys.exit(0) # try to force an exit
+    else:
+        if argv:
+            from merlin import main
+            main(['install'] + argv)
+        else:
+            print "Merlin version",branch,"has been installed."
+
+
+
+if __name__=='__main__':
+    main(sys.argv[1:])

Modified: cs/merlin/trunk/merlin/command/easy_install.py
===================================================================
--- cs/merlin/trunk/merlin/command/easy_install.py	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin/command/easy_install.py	2006-11-11 00:17:42 UTC (rev 5238)
@@ -1563,72 +1563,3 @@
         os.rmdir(path)
     except os.error:
         onerror(os.rmdir, path, sys.exc_info())
-
-
-
-
-
-
-
-def main(argv=None, **kw):
-    from merlin import setup
-    from merlin.dist import Distribution
-    import distutils.core
-
-    USAGE = """\
-usage: %(script)s [options] requirement_or_url ...
-   or: %(script)s --help
-"""
-
-    def gen_usage (script_name):
-        script = os.path.basename(script_name)
-        return USAGE % vars()
-
-    def with_ei_usage(f):
-        old_gen_usage = distutils.core.gen_usage
-        try:
-            distutils.core.gen_usage = gen_usage
-            return f()
-        finally:
-            distutils.core.gen_usage = old_gen_usage
-
-    class DistributionWithoutHelpCommands(Distribution):
-        def _show_help(self,*args,**kw):
-            with_ei_usage(lambda: Distribution._show_help(self,*args,**kw))
-
-    if argv is None:
-        argv = sys.argv[1:]
-
-    def usage():
-        print >> sys.stderr, "Usage: merlin [merlin-options] <command> [command-options-and-arguments]"
-        sys.exit(1)
-
-    def help():
-        # NYI
-        usage()
-
-    def install():
-        with_ei_usage(lambda:
-            setup(
-                script_args = ['-q','easy_install', '-v']+argv,
-                script_name = sys.argv[0] or 'easy_install',
-                distclass=DistributionWithoutHelpCommands, **kw
-            )
-        )
-    
-    if not argv:
-        usage()
-
-    command = argv.pop(0)
-    if command == 'help':
-        help()
-    elif command == 'install':
-        install()
-    else:
-        usage()
-    
-    return
-
-
-
-

Modified: cs/merlin/trunk/merlin/dist.py
===================================================================
--- cs/merlin/trunk/merlin/dist.py	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin/dist.py	2006-11-11 00:17:42 UTC (rev 5238)
@@ -633,22 +633,61 @@
             yield name
 
 
-    def find_config_files(self):
+    def parse_config_files (self, filenames=None):
 
-        filenames = _Distribution.find_config_files(self)
-        
-        # Where to look for the merlin config file
-        merlin_dir = os.path.dirname(sys.modules['merlin'].__file__)
+        import string
+        from ConfigParser import ConfigParser
+        from merlin import resource_stream
+        from distutils.debug import DEBUG
+        from distutils.errors import DistutilsOptionError
 
-        # Look for the system config file
-        merlin_file = os.path.join(merlin_dir, "distutils.cfg")
-        if os.path.isfile(merlin_file):
-            filenames.append(merlin_file)
+        if filenames is None:
+            filenames = self.find_config_files()
 
-        return filenames
+        if DEBUG: print "Distribution.parse_config_files():"
 
+        parser = ConfigParser()
 
+        fp = resource_stream(__name__, "distutils.cfg")
+        parser.readfp(fp)
 
+        for filename in filenames:
+            if DEBUG: print "  reading", filename
+            parser.read(filename)
+            for section in parser.sections():
+                options = parser.options(section)
+                opt_dict = self.get_option_dict(section)
+
+                for opt in options:
+                    if opt != '__name__':
+                        val = parser.get(section,opt)
+                        opt = string.replace(opt, '-', '_')
+                        opt_dict[opt] = (filename, val)
+
+            # Make the ConfigParser forget everything (so we retain
+            # the original filenames that options come from)
+            parser.__init__()
+
+        # If there was a "global" section in the config file, use it
+        # to set Distribution options.
+
+        if self.command_options.has_key('global'):
+            for (opt, (src, val)) in self.command_options['global'].items():
+                alias = self.negative_opt.get(opt)
+                try:
+                    if alias:
+                        setattr(self, alias, not strtobool(val))
+                    elif opt in ('verbose', 'dry_run'): # ugh!
+                        setattr(self, opt, strtobool(val))
+                    else:
+                        setattr(self, opt, val)
+                except ValueError, msg:
+                    raise DistutilsOptionError, msg
+
+    # parse_config_files ()
+
+
+
 # Install it throughout the distutils
 for module in distutils.dist, distutils.core, distutils.cmd:
     module.Distribution = Distribution

Modified: cs/merlin/trunk/merlin.egg-info/PKG-INFO
===================================================================
--- cs/merlin/trunk/merlin.egg-info/PKG-INFO	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin.egg-info/PKG-INFO	2006-11-11 00:17:42 UTC (rev 5238)
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: merlin
-Version: 1.0b1
+Version: 1.0
 Summary: A custom version of Phillip J. Eby's setuptools.
 Home-page: http://www.geodynamics.org/cig/software/packages/pythia/
 Author: Leif Strand

Modified: cs/merlin/trunk/merlin.egg-info/SOURCES.txt
===================================================================
--- cs/merlin/trunk/merlin.egg-info/SOURCES.txt	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin.egg-info/SOURCES.txt	2006-11-11 00:17:42 UTC (rev 5238)
@@ -29,6 +29,7 @@
 merlin.egg-info/entry_points.txt
 merlin.egg-info/not-zip-safe
 merlin.egg-info/top_level.txt
+merlin/archimedes/__init__.py
 merlin/command/__init__.py
 merlin/command/alias.py
 merlin/command/bdist_egg.py

Modified: cs/merlin/trunk/merlin.egg-info/entry_points.txt
===================================================================
--- cs/merlin/trunk/merlin.egg-info/entry_points.txt	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/merlin.egg-info/entry_points.txt	2006-11-11 00:17:42 UTC (rev 5238)
@@ -50,5 +50,5 @@
 sdist = merlin.command.sdist:sdist
 
 [console_scripts]
-merlin = merlin.command.easy_install:main
+merlin = merlin:main
 

Modified: cs/merlin/trunk/setup.py
===================================================================
--- cs/merlin/trunk/setup.py	2006-11-10 23:46:27 UTC (rev 5237)
+++ cs/merlin/trunk/setup.py	2006-11-11 00:17:42 UTC (rev 5238)
@@ -19,7 +19,7 @@
 d = {}; execfile(convert_path('merlin/command/__init__.py'), d)
 SETUP_COMMANDS = d['__all__']
 
-VERSION = "1.0b1"
+VERSION = "1.0"
 from merlin import setup, find_packages
 import sys
 scripts = []
@@ -79,7 +79,7 @@
 
 
         "console_scripts": [
-             "merlin = merlin.command.easy_install:main",
+             "merlin = merlin:main",
             ],
 
         "merlin.file_finders":



More information about the cig-commits mailing list