Revision f8f8ac9d2debc000a1b14bbe2468aa3a3b16d3bd authored by Rajesh Kommu on 18 April 2014, 22:33:36 UTC, committed by Rajesh Kommu on 18 April 2014, 22:33:36 UTC
1 parent f874567
Raw File
__init__.py
#!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:])
back to top