diff --git a/ChangeLog b/ChangeLog index b8deb0f..1cfcaa0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +* 0.6.5 + - Supported file: URIs + * 0.6.4 - Added some functions to bashrc - Removed installed command diff --git a/PKG-INFO b/PKG-INFO index d05f7db..5733b62 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -32,6 +32,8 @@ Install some Pythons:: pythonbrew install --configure="CC=gcc_4.1" 2.6.6 pythonbrew install --no-setuptools 2.6.6 pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.tgz + pythonbrew install file:///path/to/Python-2.7.tgz + pythonbrew install /path/to/Python-2.7.tgz Switch python in the $PATH:: @@ -121,3 +123,13 @@ Options \-n | --no-setuptools Skip installation of setuptools. + +COPYRIGHT +========= + +Copyright (c) 2010, utahta "". + +LICENCE +======= + +The MIT License diff --git a/README.rst b/README.rst index b4a8131..8fcb020 100644 --- a/README.rst +++ b/README.rst @@ -31,6 +31,8 @@ Install some Pythons:: pythonbrew install --configure="CC=gcc_4.1" 2.6.6 pythonbrew install --no-setuptools 2.6.6 pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.tgz + pythonbrew install file:///path/to/Python-2.7.tgz + pythonbrew install /path/to/Python-2.7.tgz Switch python in the $PATH:: @@ -120,3 +122,13 @@ Options \-n | --no-setuptools Skip installation of setuptools. + +COPYRIGHT +========= + +Copyright (c) 2010, utahta "". + +LICENCE +======= + +The MIT License diff --git a/pythonbrew/define.py b/pythonbrew/define.py index f08464b..c12a3bd 100644 --- a/pythonbrew/define.py +++ b/pythonbrew/define.py @@ -1,6 +1,6 @@ import os -VERSION = "0.6.4" +VERSION = "0.6.5" if os.environ.has_key("PYTHONBREW_ROOT"): ROOT = os.environ["PYTHONBREW_ROOT"] @@ -51,9 +51,9 @@ _PYTHON_VERSIONS_LIST = [ "2.4", "2.4.1", "2.4.2", "2.4.3", "2.4.4", "2.4.5", "2.4.6", "2.5", "2.5.1", "2.5.2", "2.5.3", "2.5.4", "2.5.5", "2.6", "2.6.1", "2.6.2", "2.6.3", "2.6.4", "2.6.5", "2.6.6", - "2.7", + "2.7", "2.7.1", "3.0", "3.0.1", - "3.1", "3.1.1", "3.1.2", + "3.1", "3.1.1", "3.1.2", "3.1.3", ] for version in _PYTHON_VERSIONS_LIST: PYTHON_VERSION_URL[version] = "http://www.python.org/ftp/python/%s/Python-%s.tgz" % (version, version) @@ -63,7 +63,7 @@ PYTHON_VERSION_URL["3.2a2"] = "http://www.python.org/ftp/python/3.2/Python-3.2a2 PYTHON_VERSION_URL["3.2a3"] = "http://www.python.org/ftp/python/3.2/Python-3.2a3.tgz" LATEST_VERSIONS_OF_PYTHON = ['1.5.2', '1.6.1', - '2.0.1', '2.1.3', '2.2.3', '2.3.7', '2.4.6', '2.5.5', '2.6.6', '2.7', - '3.0.1', '3.1.2', '3.2a3'] + '2.0.1', '2.1.3', '2.2.3', '2.3.7', '2.4.6', '2.5.5', '2.6.6', '2.7.1', + '3.0.1', '3.1.3', '3.2a3'] diff --git a/pythonbrew/installer.py b/pythonbrew/installer.py index 427e666..585992e 100644 --- a/pythonbrew/installer.py +++ b/pythonbrew/installer.py @@ -3,10 +3,12 @@ import sys import glob import shutil import re +import mimetypes from pythonbrew.util import makedirs, symlink, Package, is_url, splitext, Link,\ unlink, is_html, Subprocess, rm_r,\ is_macosx_snowleopard, is_python25, is_python24, is_python26,\ - unpack_downloadfile + unpack_downloadfile, is_archive_file, path_to_fileurl, is_file,\ + fileurl_to_path from pythonbrew.define import PATH_BUILD, PATH_BIN, PATH_DISTS, PATH_PYTHONS,\ PATH_ETC, PATH_SCRIPTS, PATH_SCRIPTS_PYTHONBREW,\ PATH_SCRIPTS_PYTHONBREW_COMMANDS, INSTALLER_ROOT, PATH_BIN_PYTHONBREW,\ @@ -103,11 +105,20 @@ if __name__ == "__main__": class PythonInstaller(object): def __init__(self, arg, options): if is_url(arg): - self.download_url = arg - filename = Link(self.download_url).filename - pkg = Package(splitext(filename)[0]) + name = arg + elif is_archive_file(arg): + name = path_to_fileurl(arg) + elif os.path.isdir(arg): + name = path_to_fileurl(arg) else: - pkg = Package(arg) + name = arg + + if is_url(name): + self.download_url = name + filename = Link(self.download_url).filename + pkg = Package(filename) + else: + pkg = Package(name) self.download_url = get_python_version_url(pkg.version) if not self.download_url: logger.info("Unknown python version: `%s`" % pkg.name) @@ -117,8 +128,12 @@ class PythonInstaller(object): self.install_dir = "%s/%s" % (PATH_PYTHONS, pkg.name) self.build_dir = "%s/%s" % (PATH_BUILD, pkg.name) self.download_file = "%s/%s" % (PATH_DISTS, filename) - headerinfo = get_headerinfo_from_url(self.download_url) - self.content_type = headerinfo['content-type'] + if is_file(self.download_url): + path = fileurl_to_path(self.download_url) + self.content_type = mimetypes.guess_type(path)[0] + else: + headerinfo = get_headerinfo_from_url(self.download_url) + self.content_type = headerinfo['content-type'] self.options = options self.logfile = "%s/build.log" % PATH_LOG @@ -127,12 +142,11 @@ class PythonInstaller(object): logger.info("You are already installed `%s`" % self.pkg.name) sys.exit() self.ensure() - self.download() + self.download_unpack() logger.info("") logger.info("This could take a while. You can run the following command on another shell to track the status:") logger.info(" tail -f %s" % self.logfile) logger.info("") - self.unpack() self.patch() logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir)) try: @@ -158,28 +172,31 @@ class PythonInstaller(object): logger.info("`%s` is not supported on MacOSX Snow Leopard" % self.pkg.name) sys.exit() - def download(self): + def download_unpack(self): content_type = self.content_type if is_html(content_type): logger.error("Invalid content-type: `%s`" % content_type) sys.exit(1) + if is_file(self.download_url): + path = fileurl_to_path(self.download_url) + if os.path.isdir(path): + logger.info('Copying %s into %s' % (path, self.build_dir)) + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + shutil.copytree(path, self.build_dir) + return if os.path.isfile(self.download_file): logger.info("Use the previously fetched %s" % (self.download_file)) - return - msg = Link(self.download_url).show_msg - try: - dl = Downloader() - dl.download( - msg, - self.download_url, - self.download_file - ) - except: - unlink(self.download_file) - logger.info("\nInterrupt to abort. `%s`" % (self.download_url)) - sys.exit(1) - - def unpack(self): + else: + msg = Link(self.download_url).show_msg + try: + dl = Downloader() + dl.download(msg, self.download_url, self.download_file) + except: + unlink(self.download_file) + logger.info("\nInterrupt to abort. `%s`" % (self.download_url)) + sys.exit(1) + # unpack if not unpack_downloadfile(self.content_type, self.download_file, self.build_dir): sys.exit(1) @@ -272,21 +289,11 @@ class PythonInstaller(object): dl.download(filename, download_url, download_file) install_dir = os.path.join(PATH_PYTHONS, pkgname) - if is_python3: - if os.path.isfile("%s/bin/python3" % (install_dir)): - pyexec = "%s/bin/python3" % (install_dir) - elif os.path.isfile("%s/bin/python3.0" % (install_dir)): - pyexec = "%s/bin/python3.0" % (install_dir) - else: - logger.error("Python3 binary not found. `%s`" % (install_dir)) - return - else: - pyexec = os.path.join(install_dir,"bin","python") - + path_python = os.path.join(install_dir,"bin","python") try: s = Subprocess(log=self.logfile, cwd=PATH_DISTS) logger.info("Installing distribute into %s" % install_dir) - s.check_call("%s %s" % (pyexec, filename)) + s.check_call("%s %s" % (path_python, filename)) if os.path.isfile("%s/bin/easy_install" % (install_dir)) and not is_python3: logger.info("Installing pip into %s" % install_dir) s.check_call("%s/bin/easy_install pip" % (install_dir)) diff --git a/pythonbrew/util.py b/pythonbrew/util.py index c70a831..d9605c1 100644 --- a/pythonbrew/util.py +++ b/pythonbrew/util.py @@ -6,6 +6,7 @@ import re import posixpath import tarfile import platform +import urllib from subprocess import PIPE, Popen from pythonbrew.define import PATH_BIN, PATH_PYTHONS, PATH_ETC_CURRENT,\ PATH_ETC_TEMP @@ -28,6 +29,12 @@ def is_url(name): scheme = name.split(':', 1)[0].lower() return scheme in ['http', 'https', 'file', 'ftp'] +def is_file(name): + if ':' not in name: + return False + scheme = name.split(':', 1)[0].lower() + return scheme == 'file' + def splitext(name): base, ext = os.path.splitext(name) if base.lower().endswith('.tar'): @@ -205,6 +212,18 @@ def write_temp(path): fp.write('PATH_PYTHONBREW="%s"\n' % (path)) fp.close() +def path_to_fileurl(path): + path = os.path.normcase(os.path.abspath(path)) + url = urllib.quote(path) + url = url.replace(os.path.sep, '/') + url = url.lstrip('/') + return 'file:///' + url + +def fileurl_to_path(url): + assert url.startswith('file:'), ('Illegal scheme:%s' % url) + url = '/' + url[len('file:'):].lstrip('/') + return urllib.unquote(url) + class Subprocess(object): def __init__(self, log=None, shell=True, cwd=None, print_cmd=False): self._log = log @@ -232,6 +251,8 @@ class Package(object): def __init__(self, name): self.name = None self.version = None + if is_archive_file(name): + name = splitext(name)[0] m = re.search("^Python-(.*)$", name) if m: self.name = name