diff --git a/pythonbrew/commands/install.py b/pythonbrew/commands/install.py index 1bf6bc2..19fa64c 100644 --- a/pythonbrew/commands/install.py +++ b/pythonbrew/commands/install.py @@ -1,6 +1,8 @@ from pythonbrew.basecommand import Command from pythonbrew.log import logger -from pythonbrew.installer import PythonInstaller +from pythonbrew.installer.pythoninstaller import PythonInstaller,\ + PythonInstallerMacOSX +from pythonbrew.util import is_macosx_snowleopard class InstallCommand(Command): name = "install" @@ -47,7 +49,11 @@ class InstallCommand(Command): def run_command(self, options, args): if args: # Install Python - PythonInstaller(args[0], options).install() + if is_macosx_snowleopard(): + p = PythonInstallerMacOSX(args[0], options) + else: + p = PythonInstaller(args[0], options) + p.install() else: logger.info("Unknown python version.") diff --git a/pythonbrew/define.py b/pythonbrew/define.py index 2caaebe..e0fc347 100644 --- a/pythonbrew/define.py +++ b/pythonbrew/define.py @@ -21,6 +21,7 @@ PATH_LOG = os.path.join(ROOT,"log") PATH_SCRIPTS = os.path.join(ROOT,"scripts") PATH_SCRIPTS_PYTHONBREW = os.path.join(PATH_SCRIPTS,"pythonbrew") PATH_SCRIPTS_PYTHONBREW_COMMANDS = os.path.join(PATH_SCRIPTS_PYTHONBREW,"commands") +PATH_SCRIPTS_PYTHONBREW_INSTALLER = os.path.join(PATH_SCRIPTS_PYTHONBREW,"installer") PATH_PATCHES = os.path.join(ROOT,"patches") PATH_PATCHES_MACOSX = os.path.join(PATH_PATCHES,"macosx") PATH_PATCHES_MACOSX_PYTHON25 = os.path.join(PATH_PATCHES_MACOSX,"python25") diff --git a/pythonbrew/installer/__init__.py b/pythonbrew/installer/__init__.py new file mode 100644 index 0000000..2cbc24e --- /dev/null +++ b/pythonbrew/installer/__init__.py @@ -0,0 +1,36 @@ +from pythonbrew.installer.pythonbrewinstaller import PythonbrewInstaller +from pythonbrew.log import logger +from pythonbrew.define import INSTALLER_ROOT, ROOT, PATH_ETC + +def install_pythonbrew(): + PythonbrewInstaller().install(INSTALLER_ROOT) + # pythonbrew is only for bash + shrc = yourshrc = "bashrc" + logger.info(""" +Well-done! Congratulations! + +The pythonbrew is installed as: + + %(ROOT)s + +Please add the following line to the end of your ~/.%(yourshrc)s + + source %(PATH_ETC)s/%(shrc)s + +After that, exit this shell, start a new one, and install some fresh +pythons: + + pythonbrew install 2.6.6 + pythonbrew install 2.5.5 + +For further instructions, run: + + pythonbrew help + +The default help messages will popup and tell you what to do! + +Enjoy pythonbrew at %(ROOT)s!! +""" % {'ROOT':ROOT, 'yourshrc':yourshrc, 'shrc':shrc, 'PATH_ETC':PATH_ETC}) + +def upgrade_pythonbrew(): + PythonbrewInstaller().install(INSTALLER_ROOT) diff --git a/pythonbrew/installer/pythonbrewinstaller.py b/pythonbrew/installer/pythonbrewinstaller.py new file mode 100644 index 0000000..10c980e --- /dev/null +++ b/pythonbrew/installer/pythonbrewinstaller.py @@ -0,0 +1,69 @@ +import os +import sys +import glob +import shutil +from pythonbrew.util import makedirs, rm_r +from pythonbrew.define import PATH_BUILD, PATH_BIN, PATH_DISTS, PATH_PYTHONS,\ + PATH_ETC, PATH_SCRIPTS, PATH_SCRIPTS_PYTHONBREW,\ + PATH_SCRIPTS_PYTHONBREW_COMMANDS, PATH_BIN_PYTHONBREW,\ + ROOT, PATH_LOG, PATH_PATCHES, PATH_ETC_CONFIG,\ + PATH_SCRIPTS_PYTHONBREW_INSTALLER + +class PythonbrewInstaller(object): + """pythonbrew installer: + """ + + def install(self, installer_root): + # create directories + makedirs(PATH_PYTHONS) + makedirs(PATH_BUILD) + makedirs(PATH_DISTS) + makedirs(PATH_ETC) + makedirs(PATH_BIN) + makedirs(PATH_LOG) + + # create script directories + rm_r(PATH_SCRIPTS) + makedirs(PATH_SCRIPTS) + makedirs(PATH_SCRIPTS_PYTHONBREW) + makedirs(PATH_SCRIPTS_PYTHONBREW_COMMANDS) + makedirs(PATH_SCRIPTS_PYTHONBREW_INSTALLER) + + # copy all .py files + for path in glob.glob(os.path.join(installer_root,"*.py")): + shutil.copy(path, PATH_SCRIPTS_PYTHONBREW) + for path in glob.glob(os.path.join(installer_root,"commands","*.py")): + shutil.copy(path, PATH_SCRIPTS_PYTHONBREW_COMMANDS) + for path in glob.glob(os.path.join(installer_root,"installer","*.py")): + shutil.copy(path, PATH_SCRIPTS_PYTHONBREW_INSTALLER) + + # create patches direcotry + rm_r(PATH_PATCHES) + shutil.copytree(os.path.join(installer_root,"patches"), PATH_PATCHES) + + # create a main file + fp = open("%s/pythonbrew_main.py" % PATH_SCRIPTS, "w") + fp.write("""import pythonbrew +if __name__ == "__main__": + pythonbrew.main() +""") + fp.close() + + # create entry point file + fp = open(PATH_BIN_PYTHONBREW, "w") + fp.write("""#!/usr/bin/env bash +%s %s/pythonbrew_main.py "$@" +""" % (sys.executable, PATH_SCRIPTS)) + fp.close() + os.chmod(PATH_BIN_PYTHONBREW, 0755) + + # create a bashrc for pythonbrew + fp = open(os.path.join(PATH_ETC,'bashrc'), 'w') + for line in open(os.path.join(installer_root,'etc','bashrc')): + line = line.replace('@ROOT@', ROOT) + fp.write(line) + fp.close() + + # copy config.cfg + shutil.copy(os.path.join(installer_root,'etc','config.cfg'), PATH_ETC_CONFIG) + diff --git a/pythonbrew/installer.py b/pythonbrew/installer/pythoninstaller.py similarity index 58% rename from pythonbrew/installer.py rename to pythonbrew/installer/pythoninstaller.py index 112f137..46662f2 100644 --- a/pythonbrew/installer.py +++ b/pythonbrew/installer/pythoninstaller.py @@ -1,111 +1,24 @@ import os import sys -import glob import shutil import re import mimetypes from pythonbrew.util import makedirs, symlink, Package, is_url, Link,\ unlink, is_html, Subprocess, rm_r,\ - is_macosx_snowleopard, is_python25, is_python24, is_python26,\ + is_python25, is_python24, is_python26,\ 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,\ - ROOT, PATH_LOG, DISTRIBUTE_SETUP_DLSITE, PATH_PATCHES,\ - PATH_PATCHES_MACOSX_PYTHON25, PATH_PATCHES_MACOSX_PYTHON24, PATH_ETC_CONFIG +from pythonbrew.define import PATH_BUILD, PATH_DISTS, PATH_PYTHONS,\ + ROOT, PATH_LOG, DISTRIBUTE_SETUP_DLSITE,\ + PATH_PATCHES_MACOSX_PYTHON25, PATH_PATCHES_MACOSX_PYTHON24 from pythonbrew.downloader import get_python_version_url, Downloader,\ get_headerinfo_from_url from pythonbrew.log import logger -def install_pythonbrew(): - PythonbrewInstaller().install(INSTALLER_ROOT) - - # pythonbrew is only for bash - shrc = yourshrc = "bashrc" - logger.info(""" -Well-done! Congratulations! - -The pythonbrew is installed as: - - %(ROOT)s - -Please add the following line to the end of your ~/.%(yourshrc)s - - source %(PATH_ETC)s/%(shrc)s - -After that, exit this shell, start a new one, and install some fresh -pythons: - - pythonbrew install 2.6.6 - pythonbrew install 2.5.5 - -For further instructions, run: - - pythonbrew help - -The default help messages will popup and tell you what to do! - -Enjoy pythonbrew at %(ROOT)s!! -""" % {'ROOT':ROOT, 'yourshrc':yourshrc, 'shrc':shrc, 'PATH_ETC':PATH_ETC}) - -def upgrade_pythonbrew(): - PythonbrewInstaller().install(INSTALLER_ROOT) - -class PythonbrewInstaller(object): - def install(self, installer_root): - # create directories - makedirs(PATH_PYTHONS) - makedirs(PATH_BUILD) - makedirs(PATH_DISTS) - makedirs(PATH_ETC) - makedirs(PATH_BIN) - makedirs(PATH_LOG) - - # remove old and create new script directories - rm_r(PATH_SCRIPTS) - makedirs(PATH_SCRIPTS) - makedirs(PATH_SCRIPTS_PYTHONBREW) - makedirs(PATH_SCRIPTS_PYTHONBREW_COMMANDS) - - # copy all py files - for path in glob.glob(os.path.join(installer_root,"*.py")): - shutil.copy(path, PATH_SCRIPTS_PYTHONBREW) - - for path in glob.glob(os.path.join(installer_root,"commands","*.py")): - shutil.copy(path, PATH_SCRIPTS_PYTHONBREW_COMMANDS) - - # remove old and create patches direcotry - rm_r(PATH_PATCHES) - shutil.copytree(os.path.join(installer_root,"patches"), PATH_PATCHES) - - # create a main file - fp = open("%s/pythonbrew_main.py" % PATH_SCRIPTS, "w") - fp.write("""import pythonbrew -if __name__ == "__main__": - pythonbrew.main() -""") - fp.close() - - # create entry point file - fp = open(PATH_BIN_PYTHONBREW, "w") - fp.write("""#!/usr/bin/env bash -%s %s/pythonbrew_main.py "$@" -""" % (sys.executable, PATH_SCRIPTS)) - fp.close() - os.chmod(PATH_BIN_PYTHONBREW, 0755) - - # create a bashrc for pythonbrew - fp = open(os.path.join(PATH_ETC,'bashrc'), 'w') - for line in open(os.path.join(installer_root,'etc','bashrc')): - line = line.replace('@ROOT@', ROOT) - fp.write(line) - fp.close() - - # copy config.cfg - shutil.copy(os.path.join(installer_root,'etc','config.cfg'), PATH_ETC_CONFIG) - class PythonInstaller(object): + """Python installer + """ + def __init__(self, arg, options): if is_url(arg): name = arg @@ -139,12 +52,12 @@ class PythonInstaller(object): self.content_type = headerinfo['content-type'] self.options = options self.logfile = os.path.join(PATH_LOG, 'build.log') + self.configure_options = '' def install(self): if os.path.isdir(self.install_dir): logger.info("You are already installed `%s`" % self.pkg.name) sys.exit() - self.ensure() 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:") @@ -167,14 +80,7 @@ class PythonInstaller(object): % {"pkgname":self.pkg.name}) logger.info("") logger.info(" pythonbrew switch %s" % self.pkg.alias) - - def ensure(self): - if is_macosx_snowleopard(): - version = self.pkg.version - if version < '2.6' and (version != '2.4.6' and version != '2.5.5'): - logger.info("`%s` is not supported on MacOSX Snow Leopard" % self.pkg.name) - sys.exit() - + def download_unpack(self): content_type = self.content_type if is_html(content_type): @@ -204,49 +110,11 @@ class PythonInstaller(object): sys.exit(1) def patch(self): - version = self.pkg.version - try: - s = Subprocess(log=self.logfile, cwd=self.build_dir) - patches = [] - if is_macosx_snowleopard(): - if is_python24(version): - patch_dir = PATH_PATCHES_MACOSX_PYTHON24 - patches = ['patch-configure', 'patch-Makefile.pre.in', - 'patch-Lib-cgi.py.diff', 'patch-Lib-site.py.diff', - 'patch-setup.py.diff', 'patch-Include-pyport.h', - 'patch-Mac-OSX-Makefile.in', 'patch-Mac-OSX-IDLE-Makefile.in', - 'patch-Mac-OSX-PythonLauncher-Makefile.in', 'patch-configure-badcflags.diff', - 'patch-configure-arch_only.diff', 'patch-macosmodule.diff', - 'patch-mactoolboxglue.diff', 'patch-pymactoolbox.diff', - 'patch-gestaltmodule.c.diff'] - elif is_python25(version): - patch_dir = PATH_PATCHES_MACOSX_PYTHON25 - patches = ['patch-Makefile.pre.in.diff', 'patch-Lib-cgi.py.diff', - 'patch-Lib-distutils-dist.py.diff', 'patch-setup.py.diff', - 'patch-configure-badcflags.diff', 'patch-configure-arch_only.diff', - 'patch-64bit.diff', 'patch-pyconfig.h.in.diff', - 'patch-Modules-posixmodule.c.diff', 'patch-gestaltmodule.c.diff'] - if patches: - logger.info("Patching %s" % self.pkg.name) - for patch in patches: - s.check_call("patch -p0 < %s" % os.path.join(patch_dir, patch)) - except: - logger.error("Failed to patch `%s`" % self.build_dir) - sys.exit(1) + pass def configure(self): - configure_option = "" - if is_macosx_snowleopard(): - version = self.pkg.version - if is_python24(version): - configure_option = '--with-universal-archs="intel" MACOSX_DEPLOYMENT_TARGET=10.6 CPPFLAGS="-D__DARWIN_UNIX03"' - elif is_python25(version): - configure_option = '--with-universal-archs="intel" MACOSX_DEPLOYMENT_TARGET=10.6 CPPFLAGS="-D_DARWIN_C_SOURCE"' - elif is_python26(version): - configure_option = '--with-universal-archs="intel" --enable-universalsdk=/ MACOSX_DEPLOYMENT_TARGET=10.6' - s = Subprocess(log=self.logfile, cwd=self.build_dir) - s.check_call("./configure --prefix=%s %s %s" % (self.install_dir, self.options.configure, configure_option)) + s.check_call("./configure --prefix=%s %s %s" % (self.install_dir, self.options.configure, self.configure_options)) def make(self): jobs = self.options.jobs @@ -308,5 +176,51 @@ class PythonInstaller(object): logger.error("Failed to install setuptools. See %s/build.log to see why." % (ROOT)) logger.info("Skip install setuptools.") - +class PythonInstallerMacOSX(PythonInstaller): + """Python installer for MacOSX SnowLeopard + """ + def __init__(self, arg, options): + super(PythonInstaller).__init__(arg, options) + version = self.pkg.version + # check for version + if version < '2.6' and (version != '2.4.6' and version != '2.5.5'): + logger.info("`%s` is not supported on MacOSX Snow Leopard" % self.pkg.name) + sys.exit() + # set configure options + if is_python24(version): + self.configure_options = '--with-universal-archs="intel" MACOSX_DEPLOYMENT_TARGET=10.6 CPPFLAGS="-D__DARWIN_UNIX03"' + elif is_python25(version): + self.configure_options = '--with-universal-archs="intel" MACOSX_DEPLOYMENT_TARGET=10.6 CPPFLAGS="-D_DARWIN_C_SOURCE"' + elif is_python26(version): + self.configure_options = '--with-universal-archs="intel" --enable-universalsdk=/ MACOSX_DEPLOYMENT_TARGET=10.6' + + def patch(self): + version = self.pkg.version + try: + s = Subprocess(log=self.logfile, cwd=self.build_dir) + patches = [] + if is_python24(version): + patch_dir = PATH_PATCHES_MACOSX_PYTHON24 + patches = ['patch-configure', 'patch-Makefile.pre.in', + 'patch-Lib-cgi.py.diff', 'patch-Lib-site.py.diff', + 'patch-setup.py.diff', 'patch-Include-pyport.h', + 'patch-Mac-OSX-Makefile.in', 'patch-Mac-OSX-IDLE-Makefile.in', + 'patch-Mac-OSX-PythonLauncher-Makefile.in', 'patch-configure-badcflags.diff', + 'patch-configure-arch_only.diff', 'patch-macosmodule.diff', + 'patch-mactoolboxglue.diff', 'patch-pymactoolbox.diff', + 'patch-gestaltmodule.c.diff'] + elif is_python25(version): + patch_dir = PATH_PATCHES_MACOSX_PYTHON25 + patches = ['patch-Makefile.pre.in.diff', 'patch-Lib-cgi.py.diff', + 'patch-Lib-distutils-dist.py.diff', 'patch-setup.py.diff', + 'patch-configure-badcflags.diff', 'patch-configure-arch_only.diff', + 'patch-64bit.diff', 'patch-pyconfig.h.in.diff', + 'patch-Modules-posixmodule.c.diff', 'patch-gestaltmodule.c.diff'] + if patches: + logger.info("Patching %s" % self.pkg.name) + for patch in patches: + s.check_call("patch -p0 < %s" % os.path.join(patch_dir, patch)) + except: + logger.error("Failed to patch `%s`" % self.build_dir) + sys.exit(1)