|  | #!python | 
|  | """Bootstrap distribute installation | 
|  |  | 
|  | If you want to use setuptools in your package's setup.py, just include this | 
|  | file in the same directory with it, and add this to the top of your setup.py:: | 
|  |  | 
|  | from distribute_setup import use_setuptools | 
|  | use_setuptools() | 
|  |  | 
|  | If you want to require a specific version of setuptools, set a download | 
|  | mirror, or use an alternate download directory, you can do so by supplying | 
|  | the appropriate options to ``use_setuptools()``. | 
|  |  | 
|  | This file can also be run as a script to install or upgrade setuptools. | 
|  | """ | 
|  | import os | 
|  | import sys | 
|  | import time | 
|  | import fnmatch | 
|  | import tempfile | 
|  | import tarfile | 
|  | from distutils import log | 
|  |  | 
|  | try: | 
|  | from site import USER_SITE | 
|  | except ImportError: | 
|  | USER_SITE = None | 
|  |  | 
|  | try: | 
|  | import subprocess | 
|  |  | 
|  | def _python_cmd(*args): | 
|  | args = (sys.executable,) + args | 
|  | return subprocess.call(args) == 0 | 
|  |  | 
|  | except ImportError: | 
|  | # will be used for python 2.3 | 
|  | def _python_cmd(*args): | 
|  | args = (sys.executable,) + args | 
|  | # quoting arguments if windows | 
|  | if sys.platform == 'win32': | 
|  | def quote(arg): | 
|  | if ' ' in arg: | 
|  | return '"%s"' % arg | 
|  | return arg | 
|  | args = [quote(arg) for arg in args] | 
|  | return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 | 
|  |  | 
|  | DEFAULT_VERSION = "0.6.13" | 
|  | DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" | 
|  | SETUPTOOLS_FAKED_VERSION = "0.6c11" | 
|  |  | 
|  | SETUPTOOLS_PKG_INFO = """\ | 
|  | Metadata-Version: 1.0 | 
|  | Name: setuptools | 
|  | Version: %s | 
|  | Summary: xxxx | 
|  | Home-page: xxx | 
|  | Author: xxx | 
|  | Author-email: xxx | 
|  | License: xxx | 
|  | Description: xxx | 
|  | """ % SETUPTOOLS_FAKED_VERSION | 
|  |  | 
|  |  | 
|  | def _install(tarball): | 
|  | # extracting the tarball | 
|  | tmpdir = tempfile.mkdtemp() | 
|  | log.warn('Extracting in %s', tmpdir) | 
|  | old_wd = os.getcwd() | 
|  | try: | 
|  | os.chdir(tmpdir) | 
|  | tar = tarfile.open(tarball) | 
|  | _extractall(tar) | 
|  | tar.close() | 
|  |  | 
|  | # going in the directory | 
|  | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) | 
|  | os.chdir(subdir) | 
|  | log.warn('Now working in %s', subdir) | 
|  |  | 
|  | # installing | 
|  | log.warn('Installing Distribute') | 
|  | if not _python_cmd('setup.py', 'install'): | 
|  | log.warn('Something went wrong during the installation.') | 
|  | log.warn('See the error message above.') | 
|  | finally: | 
|  | os.chdir(old_wd) | 
|  |  | 
|  |  | 
|  | def _build_egg(egg, tarball, to_dir): | 
|  | # extracting the tarball | 
|  | tmpdir = tempfile.mkdtemp() | 
|  | log.warn('Extracting in %s', tmpdir) | 
|  | old_wd = os.getcwd() | 
|  | try: | 
|  | os.chdir(tmpdir) | 
|  | tar = tarfile.open(tarball) | 
|  | _extractall(tar) | 
|  | tar.close() | 
|  |  | 
|  | # going in the directory | 
|  | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) | 
|  | os.chdir(subdir) | 
|  | log.warn('Now working in %s', subdir) | 
|  |  | 
|  | # building an egg | 
|  | log.warn('Building a Distribute egg in %s', to_dir) | 
|  | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) | 
|  |  | 
|  | finally: | 
|  | os.chdir(old_wd) | 
|  | # returning the result | 
|  | log.warn(egg) | 
|  | if not os.path.exists(egg): | 
|  | raise IOError('Could not build the egg.') | 
|  |  | 
|  |  | 
|  | def _do_download(version, download_base, to_dir, download_delay): | 
|  | egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' | 
|  | % (version, sys.version_info[0], sys.version_info[1])) | 
|  | if not os.path.exists(egg): | 
|  | tarball = download_setuptools(version, download_base, | 
|  | to_dir, download_delay) | 
|  | _build_egg(egg, tarball, to_dir) | 
|  | sys.path.insert(0, egg) | 
|  | import setuptools | 
|  | setuptools.bootstrap_install_from = egg | 
|  |  | 
|  |  | 
|  | def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, | 
|  | to_dir=os.curdir, download_delay=15, no_fake=True): | 
|  | # making sure we use the absolute path | 
|  | to_dir = os.path.abspath(to_dir) | 
|  | was_imported = 'pkg_resources' in sys.modules or \ | 
|  | 'setuptools' in sys.modules | 
|  | try: | 
|  | try: | 
|  | import pkg_resources | 
|  | if not hasattr(pkg_resources, '_distribute'): | 
|  | if not no_fake: | 
|  | _fake_setuptools() | 
|  | raise ImportError | 
|  | except ImportError: | 
|  | return _do_download(version, download_base, to_dir, download_delay) | 
|  | try: | 
|  | pkg_resources.require("distribute>="+version) | 
|  | return | 
|  | except pkg_resources.VersionConflict: | 
|  | e = sys.exc_info()[1] | 
|  | if was_imported: | 
|  | sys.stderr.write( | 
|  | "The required version of distribute (>=%s) is not available,\n" | 
|  | "and can't be installed while this script is running. Please\n" | 
|  | "install a more recent version first, using\n" | 
|  | "'easy_install -U distribute'." | 
|  | "\n\n(Currently using %r)\n" % (version, e.args[0])) | 
|  | sys.exit(2) | 
|  | else: | 
|  | del pkg_resources, sys.modules['pkg_resources']    # reload ok | 
|  | return _do_download(version, download_base, to_dir, | 
|  | download_delay) | 
|  | except pkg_resources.DistributionNotFound: | 
|  | return _do_download(version, download_base, to_dir, | 
|  | download_delay) | 
|  | finally: | 
|  | if not no_fake: | 
|  | _create_fake_setuptools_pkg_info(to_dir) | 
|  |  | 
|  | def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, | 
|  | to_dir=os.curdir, delay=15): | 
|  | """Download distribute from a specified location and return its filename | 
|  |  | 
|  | `version` should be a valid distribute version number that is available | 
|  | as an egg for download under the `download_base` URL (which should end | 
|  | with a '/'). `to_dir` is the directory where the egg will be downloaded. | 
|  | `delay` is the number of seconds to pause before an actual download | 
|  | attempt. | 
|  | """ | 
|  | # making sure we use the absolute path | 
|  | to_dir = os.path.abspath(to_dir) | 
|  | try: | 
|  | from urllib.request import urlopen | 
|  | except ImportError: | 
|  | from urllib2 import urlopen | 
|  | tgz_name = "distribute-%s.tar.gz" % version | 
|  | url = download_base + tgz_name | 
|  | saveto = os.path.join(to_dir, tgz_name) | 
|  | src = dst = None | 
|  | if not os.path.exists(saveto):  # Avoid repeated downloads | 
|  | try: | 
|  | log.warn("Downloading %s", url) | 
|  | src = 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 _no_sandbox(function): | 
|  | def __no_sandbox(*args, **kw): | 
|  | try: | 
|  | from setuptools.sandbox import DirectorySandbox | 
|  | if not hasattr(DirectorySandbox, '_old'): | 
|  | def violation(*args): | 
|  | pass | 
|  | DirectorySandbox._old = DirectorySandbox._violation | 
|  | DirectorySandbox._violation = violation | 
|  | patched = True | 
|  | else: | 
|  | patched = False | 
|  | except ImportError: | 
|  | patched = False | 
|  |  | 
|  | try: | 
|  | return function(*args, **kw) | 
|  | finally: | 
|  | if patched: | 
|  | DirectorySandbox._violation = DirectorySandbox._old | 
|  | del DirectorySandbox._old | 
|  |  | 
|  | return __no_sandbox | 
|  |  | 
|  | def _patch_file(path, content): | 
|  | """Will backup the file then patch it""" | 
|  | existing_content = open(path).read() | 
|  | if existing_content == content: | 
|  | # already patched | 
|  | log.warn('Already patched.') | 
|  | return False | 
|  | log.warn('Patching...') | 
|  | _rename_path(path) | 
|  | f = open(path, 'w') | 
|  | try: | 
|  | f.write(content) | 
|  | finally: | 
|  | f.close() | 
|  | return True | 
|  |  | 
|  | _patch_file = _no_sandbox(_patch_file) | 
|  |  | 
|  | def _same_content(path, content): | 
|  | return open(path).read() == content | 
|  |  | 
|  | def _rename_path(path): | 
|  | new_name = path + '.OLD.%s' % time.time() | 
|  | log.warn('Renaming %s into %s', path, new_name) | 
|  | os.rename(path, new_name) | 
|  | return new_name | 
|  |  | 
|  | def _remove_flat_installation(placeholder): | 
|  | if not os.path.isdir(placeholder): | 
|  | log.warn('Unkown installation at %s', placeholder) | 
|  | return False | 
|  | found = False | 
|  | for file in os.listdir(placeholder): | 
|  | if fnmatch.fnmatch(file, 'setuptools*.egg-info'): | 
|  | found = True | 
|  | break | 
|  | if not found: | 
|  | log.warn('Could not locate setuptools*.egg-info') | 
|  | return | 
|  |  | 
|  | log.warn('Removing elements out of the way...') | 
|  | pkg_info = os.path.join(placeholder, file) | 
|  | if os.path.isdir(pkg_info): | 
|  | patched = _patch_egg_dir(pkg_info) | 
|  | else: | 
|  | patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) | 
|  |  | 
|  | if not patched: | 
|  | log.warn('%s already patched.', pkg_info) | 
|  | return False | 
|  | # now let's move the files out of the way | 
|  | for element in ('setuptools', 'pkg_resources.py', 'site.py'): | 
|  | element = os.path.join(placeholder, element) | 
|  | if os.path.exists(element): | 
|  | _rename_path(element) | 
|  | else: | 
|  | log.warn('Could not find the %s element of the ' | 
|  | 'Setuptools distribution', element) | 
|  | return True | 
|  |  | 
|  | _remove_flat_installation = _no_sandbox(_remove_flat_installation) | 
|  |  | 
|  | def _after_install(dist): | 
|  | log.warn('After install bootstrap.') | 
|  | placeholder = dist.get_command_obj('install').install_purelib | 
|  | _create_fake_setuptools_pkg_info(placeholder) | 
|  |  | 
|  | def _create_fake_setuptools_pkg_info(placeholder): | 
|  | if not placeholder or not os.path.exists(placeholder): | 
|  | log.warn('Could not find the install location') | 
|  | return | 
|  | pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) | 
|  | setuptools_file = 'setuptools-%s-py%s.egg-info' % \ | 
|  | (SETUPTOOLS_FAKED_VERSION, pyver) | 
|  | pkg_info = os.path.join(placeholder, setuptools_file) | 
|  | if os.path.exists(pkg_info): | 
|  | log.warn('%s already exists', pkg_info) | 
|  | return | 
|  |  | 
|  | log.warn('Creating %s', pkg_info) | 
|  | f = open(pkg_info, 'w') | 
|  | try: | 
|  | f.write(SETUPTOOLS_PKG_INFO) | 
|  | finally: | 
|  | f.close() | 
|  |  | 
|  | pth_file = os.path.join(placeholder, 'setuptools.pth') | 
|  | log.warn('Creating %s', pth_file) | 
|  | f = open(pth_file, 'w') | 
|  | try: | 
|  | f.write(os.path.join(os.curdir, setuptools_file)) | 
|  | finally: | 
|  | f.close() | 
|  |  | 
|  | _create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info) | 
|  |  | 
|  | def _patch_egg_dir(path): | 
|  | # let's check if it's already patched | 
|  | pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') | 
|  | if os.path.exists(pkg_info): | 
|  | if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): | 
|  | log.warn('%s already patched.', pkg_info) | 
|  | return False | 
|  | _rename_path(path) | 
|  | os.mkdir(path) | 
|  | os.mkdir(os.path.join(path, 'EGG-INFO')) | 
|  | pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') | 
|  | f = open(pkg_info, 'w') | 
|  | try: | 
|  | f.write(SETUPTOOLS_PKG_INFO) | 
|  | finally: | 
|  | f.close() | 
|  | return True | 
|  |  | 
|  | _patch_egg_dir = _no_sandbox(_patch_egg_dir) | 
|  |  | 
|  | def _before_install(): | 
|  | log.warn('Before install bootstrap.') | 
|  | _fake_setuptools() | 
|  |  | 
|  |  | 
|  | def _under_prefix(location): | 
|  | if 'install' not in sys.argv: | 
|  | return True | 
|  | args = sys.argv[sys.argv.index('install')+1:] | 
|  | for index, arg in enumerate(args): | 
|  | for option in ('--root', '--prefix'): | 
|  | if arg.startswith('%s=' % option): | 
|  | top_dir = arg.split('root=')[-1] | 
|  | return location.startswith(top_dir) | 
|  | elif arg == option: | 
|  | if len(args) > index: | 
|  | top_dir = args[index+1] | 
|  | return location.startswith(top_dir) | 
|  | if arg == '--user' and USER_SITE is not None: | 
|  | return location.startswith(USER_SITE) | 
|  | return True | 
|  |  | 
|  |  | 
|  | def _fake_setuptools(): | 
|  | log.warn('Scanning installed packages') | 
|  | try: | 
|  | import pkg_resources | 
|  | except ImportError: | 
|  | # we're cool | 
|  | log.warn('Setuptools or Distribute does not seem to be installed.') | 
|  | return | 
|  | ws = pkg_resources.working_set | 
|  | try: | 
|  | setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', | 
|  | replacement=False)) | 
|  | except TypeError: | 
|  | # old distribute API | 
|  | setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) | 
|  |  | 
|  | if setuptools_dist is None: | 
|  | log.warn('No setuptools distribution found') | 
|  | return | 
|  | # detecting if it was already faked | 
|  | setuptools_location = setuptools_dist.location | 
|  | log.warn('Setuptools installation detected at %s', setuptools_location) | 
|  |  | 
|  | # if --root or --preix was provided, and if | 
|  | # setuptools is not located in them, we don't patch it | 
|  | if not _under_prefix(setuptools_location): | 
|  | log.warn('Not patching, --root or --prefix is installing Distribute' | 
|  | ' in another location') | 
|  | return | 
|  |  | 
|  | # let's see if its an egg | 
|  | if not setuptools_location.endswith('.egg'): | 
|  | log.warn('Non-egg installation') | 
|  | res = _remove_flat_installation(setuptools_location) | 
|  | if not res: | 
|  | return | 
|  | else: | 
|  | log.warn('Egg installation') | 
|  | pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') | 
|  | if (os.path.exists(pkg_info) and | 
|  | _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): | 
|  | log.warn('Already patched.') | 
|  | return | 
|  | log.warn('Patching...') | 
|  | # let's create a fake egg replacing setuptools one | 
|  | res = _patch_egg_dir(setuptools_location) | 
|  | if not res: | 
|  | return | 
|  | log.warn('Patched done.') | 
|  | _relaunch() | 
|  |  | 
|  |  | 
|  | def _relaunch(): | 
|  | log.warn('Relaunching...') | 
|  | # we have to relaunch the process | 
|  | # pip marker to avoid a relaunch bug | 
|  | if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: | 
|  | sys.argv[0] = 'setup.py' | 
|  | args = [sys.executable] + sys.argv | 
|  | sys.exit(subprocess.call(args)) | 
|  |  | 
|  |  | 
|  | def _extractall(self, path=".", members=None): | 
|  | """Extract all members from the archive to the current working | 
|  | directory and set owner, modification time and permissions on | 
|  | directories afterwards. `path' specifies a different directory | 
|  | to extract to. `members' is optional and must be a subset of the | 
|  | list returned by getmembers(). | 
|  | """ | 
|  | import copy | 
|  | import operator | 
|  | from tarfile import ExtractError | 
|  | directories = [] | 
|  |  | 
|  | if members is None: | 
|  | members = self | 
|  |  | 
|  | for tarinfo in members: | 
|  | if tarinfo.isdir(): | 
|  | # Extract directories with a safe mode. | 
|  | directories.append(tarinfo) | 
|  | tarinfo = copy.copy(tarinfo) | 
|  | tarinfo.mode = 448 # decimal for oct 0700 | 
|  | self.extract(tarinfo, path) | 
|  |  | 
|  | # Reverse sort directories. | 
|  | if sys.version_info < (2, 4): | 
|  | def sorter(dir1, dir2): | 
|  | return cmp(dir1.name, dir2.name) | 
|  | directories.sort(sorter) | 
|  | directories.reverse() | 
|  | else: | 
|  | directories.sort(key=operator.attrgetter('name'), reverse=True) | 
|  |  | 
|  | # Set correct owner, mtime and filemode on directories. | 
|  | for tarinfo in directories: | 
|  | dirpath = os.path.join(path, tarinfo.name) | 
|  | try: | 
|  | self.chown(tarinfo, dirpath) | 
|  | self.utime(tarinfo, dirpath) | 
|  | self.chmod(tarinfo, dirpath) | 
|  | except ExtractError: | 
|  | e = sys.exc_info()[1] | 
|  | if self.errorlevel > 1: | 
|  | raise | 
|  | else: | 
|  | self._dbg(1, "tarfile: %s" % e) | 
|  |  | 
|  |  | 
|  | def main(argv, version=DEFAULT_VERSION): | 
|  | """Install or upgrade setuptools and EasyInstall""" | 
|  | tarball = download_setuptools() | 
|  | _install(tarball) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | main(sys.argv[1:]) |