release 0.8

This commit is contained in:
utahta
2011-07-11 00:22:48 +09:00
parent 7371bde921
commit cfdd193ffe
26 changed files with 743 additions and 252 deletions
+14 -3
View File
@@ -1,9 +1,20 @@
* 0.8
- Fixed issue #21 Added Ubuntu 11.04(Natty) support
- Fixed issue #24 non-framework python27 now defines environ properly. Thanks npinto.
- Fixed issue #27 Cleanup of OS X python build flags
- Fixed issue #28 Describe the 'symlink' command better. Thanks tgs.
- Fixed issue #30 py command does not accept arguments with a space
- Fixed bug: `pythonbrew off` need not have removed the symlink in bin directory
- Added --no-test option to the install command
- Added --verbose option to the install command
- `pythonbrew clean` has been renamed. Added `pythonbrew cleanup` instead.
* 0.7.3
- Improved symlink command.
- support python3
- Improved symlink command
- Added python3 support
* 0.7.2
- Bug fixed.
- Bug fixed
* 0.7.1
- Enable parallel make option (--jobs).
-1
View File
@@ -1 +0,0 @@
README.rst
+159
View File
@@ -0,0 +1,159 @@
Overview
========
pythonbrew is a program to automate the building and installation of Python in the users $HOME.
pythonbrew is inspired by `perlbrew <http://github.com/gugod/App-perlbrew>`_ and `rvm <https://github.com/wayneeseguin/rvm>`_.
Installation
============
The recommended way to download and install pythonbrew is to run these statements in your shell::
curl -kL http://xrl.us/pythonbrewinstall | bash
After that, pythonbrew installs itself to ~/.pythonbrew, and you should follow the instruction on screen to setup your .bashrc to put it in your PATH.
If you need to install pythonbrew into somewhere else, you can do that by setting a PYTHONBREW_ROOT environment variable::
export PYTHONBREW_ROOT=/path/to/pythonbrew
curl -kLO http://xrl.us/pythonbrewinstall
chmod +x pythonbrewinstall
./pythonbrewinstall
Usage
=====
pythonbrew command [options]
Install some pythons::
pythonbrew install 2.7.2
pythonbrew install --verbose 2.7.2
pythonbrew install --force 2.7.2
pythonbrew install --no-test 2.7.2
pythonbrew install --configure="CC=gcc_4.1" 2.7.2
pythonbrew install --no-setuptools 2.7.2
pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2
pythonbrew install 2.7.2 3.2
Permanently use the specified python::
pythonbrew switch 2.7.2
pythonbrew switch 3.2
Use the specified python in current shell::
pythonbrew use 2.7.2
Runs a named python file against specified and/or all pythons::
pythonbrew py test.py
pythonbrew py -v test.py # Show running python version
pythonbrew py -p 2.7.2 -p 3.2 test.py # Use the specified pythons
List the installed pythons::
pythonbrew list
List the available installation pythons::
pythonbrew list -k
Uninstall the specified python::
pythonbrew uninstall 2.7.2
pythonbrew uninstall 2.7.2 3.2
Remove stale source folders and archives::
pythonbrew cleanup
Upgrades pythonbrew to the latest version::
pythonbrew update
pythonbrew update --master
pythonbrew update --develop
Disable pythonbrew::
pythonbrew off
Create/Remove a symbolic link to python (in a directory on your $PATH)::
pythonbrew symlink # Create a symbolic link, like "py2.7.2", for each installed version
pythonbrew symlink -p 2.7.2
pythonbrew symlink pip # Create a symbolic link to the specified script in bin directory
pythonbrew symlink -r # Remove a symbolic link
Show version::
pythonbrew version
COMMANDS
========
install <version>
Build and install the given version of python.
Install setuptools and pip automatically.
switch <version>
Permanently use the specified python as default.
use <version>
Use the specified python in current shell.
py <python file>
Runs a named python file against specified and/or all pythons.
list
List the installed all pythons.
list -k <version>
List the available install pythons.
uninstall <version>
Uninstall the given version of python.
cleanup
Remove stale source folders and archives.
update
Upgrades pythonbrew to the latest version.
off
Disable pythonbrew.
version
Show version.
See more details below::
pythonbrew help <command>
LICENCE
=======
The MIT License
Copyright (c) <2010-2011> <utahta>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+33 -47
View File
@@ -1,7 +1,7 @@
Overview
========
pythonbrew is a program to automate the building and installation of Python in the users HOME.
pythonbrew is a program to automate the building and installation of Python in the users $HOME.
pythonbrew is inspired by `perlbrew <http://github.com/gugod/App-perlbrew>`_ and `rvm <https://github.com/wayneeseguin/rvm>`_.
@@ -10,20 +10,16 @@ Installation
The recommended way to download and install pythonbrew is to run these statements in your shell::
curl -kLO http://github.com/utahta/pythonbrew/raw/master/pythonbrew-install
chmod +x pythonbrew-install
./pythonbrew-install
or more simply like this::
curl -kL http://github.com/utahta/pythonbrew/raw/master/pythonbrew-install | bash
curl -kL http://xrl.us/pythonbrewinstall | bash
After that, pythonbrew installs itself to ~/.pythonbrew, and you should follow the instruction on screen to setup your .bashrc to put it in your PATH.
If you need to install pythonbrew into somewhere else, you can do that by setting a PYTHONBREW_ROOT environment variable::
export PYTHONBREW_ROOT=/path/to/pythonbrew
./pythonbrew-install
curl -kLO http://xrl.us/pythonbrewinstall
chmod +x pythonbrewinstall
./pythonbrewinstall
Usage
=====
@@ -32,50 +28,54 @@ pythonbrew command [options]
Install some pythons::
pythonbrew install 2.6.6
pythonbrew install --force 2.6.6
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.6.6.tgz
pythonbrew install file:///path/to/Python-2.6.6.tgz
pythonbrew install /path/to/Python-2.6.6.tgz
pythonbrew install 2.5.5 2.6.6
pythonbrew install 2.7.2
pythonbrew install --verbose 2.7.2
pythonbrew install --force 2.7.2
pythonbrew install --no-test 2.7.2
pythonbrew install --configure="CC=gcc_4.1" 2.7.2
pythonbrew install --no-setuptools 2.7.2
pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2
pythonbrew install 2.7.2 3.2
Permanently use the specified python as default::
Permanently use the specified python::
pythonbrew switch 2.6.6
pythonbrew switch 2.5.5
pythonbrew switch 2.7.2
pythonbrew switch 3.2
Use the specified python in current shell::
pythonbrew use 2.6.6
pythonbrew use 2.7.2
Runs a named python file against specified and/or all pythons::
pythonbrew py test.py
pythonbrew py -v test.py # Show running python version
pythonbrew py -p 2.6.6 -p 3.1.2 test.py # Use the specified pythons
pythonbrew py -p 2.7.2 -p 3.2 test.py # Use the specified pythons
List the installed pythons::
pythonbrew list
List the available install pythons::
List the available installation pythons::
pythonbrew list -k
Uninstall the specified python::
pythonbrew uninstall 2.6.6
pythonbrew uninstall 2.5.5 2.6.6
pythonbrew uninstall 2.7.2
pythonbrew uninstall 2.7.2 3.2
Remove stale source folders and archives::
pythonbrew clean
pythonbrew cleanup
Upgrades pythonbrew to the latest version::
pythonbrew update
pythonbrew update --master
pythonbrew update --develop
Disable pythonbrew::
@@ -83,8 +83,8 @@ Disable pythonbrew::
Create/Remove a symbolic link to python (in a directory on your $PATH)::
pythonbrew symlink # Create a symbolic link, like "py2.5.5", for each installed version
pythonbrew symlink -p 2.5.5
pythonbrew symlink # Create a symbolic link, like "py2.7.2", for each installed version
pythonbrew symlink -p 2.7.2
pythonbrew symlink pip # Create a symbolic link to the specified script in bin directory
pythonbrew symlink -r # Remove a symbolic link
@@ -97,10 +97,7 @@ COMMANDS
install <version>
Build and install the given version of python.
Setuptools and pip is automatically installed.
options: --force, --no-setuptools, --configure and --as.
Install setuptools and pip automatically.
switch <version>
Permanently use the specified python as default.
@@ -120,7 +117,7 @@ list -k <version>
uninstall <version>
Uninstall the given version of python.
clean
cleanup
Remove stale source folders and archives.
update
@@ -131,21 +128,10 @@ off
version
Show version.
See more details below::
Options
=======
\-f | --force
Force installation of a python. (skip `make test`)
\-C | --configure
Custom configure options.
\-n | --no-setuptools
Skip installation of setuptools.
\--as
Install a python under an alias.
pythonbrew help <command>
LICENCE
=======
+5
View File
@@ -1,6 +1,7 @@
import sys
from pythonbrew.basecommand import command_dict, load_all_commands
from pythonbrew.baseparser import parser
from pythonbrew.log import logger
def main():
options, args = parser.parse_args(sys.argv[1:])
@@ -12,6 +13,10 @@ def main():
load_all_commands()
command = args[0].lower()
if command not in command_dict:
if command == 'clean':
# note: for some time
logger.info('\nDEPRECATION WARNING: `pythonbrew clean` has been renamed. Please run `pythonbrew cleanup` instead.\n')
return
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
@@ -3,17 +3,17 @@ from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_BUILD, PATH_DISTS
from pythonbrew.util import rm_r
class CleanCommand(Command):
name = "clean"
class CleanupCommand(Command):
name = "cleanup"
usage = "%prog"
summary = "Remove stale source folders and archives"
def run_command(self, options, args):
self._clean(PATH_BUILD)
self._clean(PATH_DISTS)
self._cleanup(PATH_BUILD)
self._cleanup(PATH_DISTS)
def _clean(self, root):
def _cleanup(self, root):
for dir in os.listdir(root):
rm_r(os.path.join(root, dir))
CleanCommand()
CleanupCommand()
+1 -1
View File
@@ -22,6 +22,6 @@ class HelpCommand(Command):
for command in commands:
logger.info(" %s: %s" % (command.name, command.summary))
logger.info("\nFurther Instructions:")
logger.info(" http://github.com/utahta/pythonbrew")
logger.info(" https://github.com/utahta/pythonbrew")
HelpCommand()
+20 -6
View File
@@ -2,7 +2,7 @@ from pythonbrew.basecommand import Command
from pythonbrew.log import logger
from pythonbrew.installer.pythoninstaller import PythonInstaller,\
PythonInstallerMacOSX
from pythonbrew.util import is_macosx_snowleopard
from pythonbrew.util import is_macosx
from pythonbrew.exceptions import UnknownVersionException,\
AlreadyInstalledException, NotSupportedVersionException
@@ -18,7 +18,21 @@ class InstallCommand(Command):
dest="force",
action="store_true",
default=False,
help="Force install of python.(skip make test)"
help="Force installation of python."
)
self.parser.add_option(
"-n", "--no-test",
dest="no_test",
action="store_true",
default=False,
help="Skip `make test`."
)
self.parser.add_option(
"-v", "--verbose",
dest="verbose",
action="store_true",
default=False,
help="Display log information on the console."
)
self.parser.add_option(
"-C", "--configure",
@@ -28,11 +42,11 @@ class InstallCommand(Command):
help="Options passed directly to configure."
)
self.parser.add_option(
"-n", "--no-setuptools",
"--no-setuptools",
dest="no_setuptools",
action="store_true",
default=False,
help="Skip install of setuptools."
help="Skip installation of setuptools."
)
self.parser.add_option(
"--as",
@@ -50,10 +64,10 @@ class InstallCommand(Command):
def run_command(self, options, args):
if args:
# Install pythons
# installing python
for arg in args:
try:
if is_macosx_snowleopard():
if is_macosx():
p = PythonInstallerMacOSX(arg, options)
else:
p = PythonInstaller(arg, options)
+3 -5
View File
@@ -1,10 +1,10 @@
import os
import sys
import subprocess
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS
from pythonbrew.util import Package
from pythonbrew.log import logger
from subprocess import Popen
class PyCommand(Command):
name = "py"
@@ -40,13 +40,11 @@ class PyCommand(Command):
logger.info('*** %s ***' % d)
path = os.path.join(PATH_PYTHONS, d, 'bin', args[0])
if os.path.isfile(path) and os.access(path, os.X_OK):
p = Popen([path] + args[1:])
p.wait()
subprocess.call([path] + args[1:])
else:
path = os.path.join(PATH_PYTHONS, d, 'bin', 'python')
if os.path.isfile(path) and os.access(path, os.X_OK):
p = Popen([path] + args)
p.wait()
subprocess.call([path] + args)
else:
logger.info('%s: No such file or directory.' % path)
+21 -13
View File
@@ -6,7 +6,7 @@ from pythonbrew.define import PATH_DISTS, VERSION, ROOT,\
from pythonbrew.log import logger
from pythonbrew.downloader import Downloader, get_pythonbrew_update_url,\
get_stable_version, get_headerinfo_from_url
from pythonbrew.util import rm_r, unpack_downloadfile, Link, is_gzip, Subprocess
from pythonbrew.util import rm_r, extract_downloadfile, Link, is_gzip, Subprocess
class UpdateCommand(Command):
name = "update"
@@ -16,11 +16,18 @@ class UpdateCommand(Command):
def __init__(self):
super(UpdateCommand, self).__init__()
self.parser.add_option(
'--head',
dest='head',
'--master',
dest='master',
action='store_true',
default=False,
help='Update the pythonbrew to the github version.'
help='Update the pythonbrew to the `master` branch on github.'
)
self.parser.add_option(
'--develop',
dest='develop',
action='store_true',
default=False,
help='Update the pythonbrew to the `develop` branch on github.'
)
self.parser.add_option(
'--config',
@@ -61,9 +68,10 @@ class UpdateCommand(Command):
logger.info("The config.cfg has been updated.")
def _update_pythonbrew(self, options, args):
# pythonbrew update
if options.head:
version = 'head'
if options.master:
version = 'master'
elif options.develop:
version = 'develop'
else:
version = get_stable_version()
# check for version
@@ -77,10 +85,10 @@ class UpdateCommand(Command):
sys.exit(1)
headinfo = get_headerinfo_from_url(download_url)
content_type = headinfo['content-type']
# head is only for gzip.
if not options.head and not is_gzip(content_type, Link(download_url).filename):
logger.error("Invalid content-type: `%s`" % content_type)
sys.exit(1)
if not options.master and not options.develop:
if not is_gzip(content_type, Link(download_url).filename):
logger.error("content type should be gzip. content-type:`%s`" % content_type)
sys.exit(1)
filename = "pythonbrew-%s" % version
distname = "%s.tgz" % filename
@@ -94,13 +102,13 @@ class UpdateCommand(Command):
extract_dir = os.path.join(PATH_BUILD, filename)
rm_r(extract_dir)
if not unpack_downloadfile(content_type, download_file, extract_dir):
if not extract_downloadfile(content_type, download_file, extract_dir):
sys.exit(1)
try:
logger.info("Installing %s into %s" % (extract_dir, ROOT))
s = Subprocess()
s.check_call('%s %s/pythonbrew_install.py --upgrade' % (sys.executable, extract_dir))
s.check_call([sys.executable, os.path.join(extract_dir,'pythonbrew_install.py'), '--upgrade'])
except:
logger.error("Failed to update pythonbrew.")
sys.exit(1)
+3 -3
View File
@@ -3,7 +3,7 @@ import re
import subprocess
from subprocess import Popen, PIPE
from pythonbrew.log import logger
from pythonbrew.util import u
from pythonbrew.util import to_str
class Curl(object):
def __init__(self):
@@ -26,11 +26,11 @@ class Curl(object):
raise
respinfo = {}
for line in p.stdout:
line = u(line.strip())
line = to_str(line.strip())
if re.match('^HTTP.*? 200 OK$', line):
break
for line in p.stdout:
line = u(line.strip()).split(":", 1)
line = to_str(line.strip()).split(":", 1)
if len(line) == 2:
respinfo[line[0].strip().lower()] = line[1].strip()
return respinfo
+4 -2
View File
@@ -6,7 +6,7 @@ except:
import configparser as ConfigParser
# pythonbrew version
VERSION = "0.7.3"
VERSION = "0.8"
# pythonbrew root path
ROOT = os.environ.get("PYTHONBREW_ROOT")
@@ -28,6 +28,7 @@ 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_ALL = os.path.join(PATH_PATCHES,"all")
PATH_PATCHES_MACOSX = os.path.join(PATH_PATCHES,"macosx")
PATH_PATCHES_MACOSX_PYTHON27 = os.path.join(PATH_PATCHES_MACOSX,"python27")
PATH_PATCHES_MACOSX_PYTHON26 = os.path.join(PATH_PATCHES_MACOSX,"python26")
@@ -53,7 +54,8 @@ def _get_or_default(section, option, default=''):
DISTRIBUTE_SETUP_DLSITE = _get_or_default('distribute', 'url')
# pythonbrew download
PYTHONBREW_UPDATE_URL_HEAD = _get_or_default('pythonbrew', 'head')
PYTHONBREW_UPDATE_URL_MASTER = _get_or_default('pythonbrew', 'master')
PYTHONBREW_UPDATE_URL_DEVELOP = _get_or_default('pythonbrew', 'develop')
PYTHONBREW_UPDATE_URL_PYPI = _get_or_default('pythonbrew', 'pypi')
PYTHONBREW_UPDATE_URL_CONFIG = _get_or_default('pythonbrew', 'config')
+8 -5
View File
@@ -1,8 +1,9 @@
from pythonbrew.define import PYTHON_VERSION_URL, PYTHONBREW_STABLE_VERSION_URL, \
PYTHONBREW_UPDATE_URL_PYPI, PYTHONBREW_UPDATE_URL_HEAD
PYTHONBREW_UPDATE_URL_PYPI, PYTHONBREW_UPDATE_URL_MASTER,\
PYTHONBREW_UPDATE_URL_DEVELOP
from pythonbrew.log import logger
from pythonbrew.curl import Curl
from pythonbrew.util import u
from pythonbrew.util import to_str
def get_headerinfo_from_url(url):
c = Curl()
@@ -10,7 +11,7 @@ def get_headerinfo_from_url(url):
def get_stable_version():
c = Curl()
return u(c.read(PYTHONBREW_STABLE_VERSION_URL).strip())
return to_str(c.read(PYTHONBREW_STABLE_VERSION_URL).strip())
class Downloader(object):
def download(self, msg, url, path):
@@ -19,8 +20,10 @@ class Downloader(object):
c.fetch(url, path)
def get_pythonbrew_update_url(version):
if version == "head":
return PYTHONBREW_UPDATE_URL_HEAD
if version == "master":
return PYTHONBREW_UPDATE_URL_MASTER
elif version == 'develop':
return PYTHONBREW_UPDATE_URL_DEVELOP
else:
return PYTHONBREW_UPDATE_URL_PYPI % (version)
+2 -1
View File
@@ -2,7 +2,8 @@
url = http://python-distribute.org/distribute_setup.py
[pythonbrew]
head = https://github.com/utahta/pythonbrew/tarball/master
master = https://github.com/utahta/pythonbrew/tarball/master
develop = https://github.com/utahta/pythonbrew/tarball/develop
pypi = http://pypi.python.org/packages/source/p/pythonbrew/pythonbrew-%%s.tar.gz
stable-version = https://github.com/utahta/pythonbrew/raw/master/stable-version.txt
config = https://github.com/utahta/pythonbrew/raw/master/pythonbrew/etc/config.cfg
+2 -2
View File
@@ -20,8 +20,8 @@ Please add the following line to the end of your ~/.%(yourshrc)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
pythonbrew install 2.7.2
pythonbrew install 3.2
For further instructions, run:
+149 -107
View File
@@ -5,12 +5,13 @@ import mimetypes
from pythonbrew.util import makedirs, symlink, Package, is_url, Link,\
unlink, is_html, Subprocess, rm_r,\
is_python25, is_python24, is_python26, is_python27,\
unpack_downloadfile, is_archive_file, path_to_fileurl, is_file,\
fileurl_to_path
extract_downloadfile, is_archive_file, path_to_fileurl, is_file,\
fileurl_to_path, is_python30, is_python31, is_python32,\
get_macosx_deployment_target
from pythonbrew.define import PATH_BUILD, PATH_DISTS, PATH_PYTHONS,\
ROOT, PATH_LOG, DISTRIBUTE_SETUP_DLSITE,\
PATH_PATCHES_MACOSX_PYTHON25, PATH_PATCHES_MACOSX_PYTHON24,\
PATH_PATCHES_MACOSX_PYTHON26, PATH_PATCHES_MACOSX_PYTHON27
PATH_PATCHES_MACOSX_PYTHON26, PATH_PATCHES_MACOSX_PYTHON27, PATH_PATCHES_ALL
from pythonbrew.downloader import get_python_version_url, Downloader,\
get_headerinfo_from_url
from pythonbrew.log import logger
@@ -22,15 +23,13 @@ class PythonInstaller(object):
"""
def __init__(self, arg, options):
if is_url(arg):
name = arg
elif is_archive_file(arg):
if is_archive_file(arg):
name = path_to_fileurl(arg)
elif os.path.isdir(arg):
name = path_to_fileurl(arg)
else:
name = arg
if is_url(name):
self.download_url = name
filename = Link(self.download_url).filename
@@ -46,25 +45,35 @@ class PythonInstaller(object):
self.install_dir = os.path.join(PATH_PYTHONS, pkg.name)
self.build_dir = os.path.join(PATH_BUILD, pkg.name)
self.download_file = os.path.join(PATH_DISTS, filename)
# cleanup
if os.path.isdir(self.build_dir):
shutil.rmtree(self.build_dir)
# get 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']
if is_html(self.content_type):
# note: maybe got 404 or 503 http status code.
logger.error("Invalid content-type: `%s`" % self.content_type)
return
self.options = options
self.logfile = os.path.join(PATH_LOG, 'build.log')
self.configure_options = ''
self.patches = []
def install(self):
if os.path.isdir(self.install_dir):
logger.info("You are already installed `%s`" % self.pkg.name)
raise AlreadyInstalledException
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.download_and_extract()
logger.info("\nThis could take a while. You can run the following command on another shell to track the status:")
logger.info(" tail -f %s\n" % self.logfile)
self.patch()
logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir))
try:
@@ -81,57 +90,105 @@ class PythonInstaller(object):
logger.info("Installed %(pkgname)s successfully. Run the following command to switch to %(pkgname)s."
% {"pkgname":self.pkg.name})
logger.info(" pythonbrew switch %s" % self.pkg.alias)
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)
def download_and_extract(self):
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))
else:
msg = Link(self.download_url).show_msg
base_url = Link(self.download_url).base_url
try:
dl = Downloader()
dl.download(msg, self.download_url, self.download_file)
dl.download(base_url, 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):
# extracting
if not extract_downloadfile(self.content_type, self.download_file, self.build_dir):
sys.exit(1)
def patch(self):
pass
version = self.pkg.version
# for ubuntu 11.04(Natty)
if is_python24(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python24")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python25(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python25")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python26(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python27(version):
if version < '2.7.2':
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python30(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python30")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python31(version):
if version < '3.1.4':
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python32(version):
if version == '3.2':
patch_dir = os.path.join(PATH_PATCHES_ALL, "python32")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
self._do_patch()
def _do_patch(self):
try:
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
if self.patches:
logger.info("Patching %s" % self.pkg.name)
for patch in self.patches:
if type(patch) is dict:
for (ed, source) in patch.items():
s.shell('ed - %s < %s' % (source, ed))
else:
s.shell("patch -p0 < %s" % patch)
except:
logger.error("Failed to patch `%s`" % self.build_dir)
sys.exit(1)
def _add_patches_to_list(self, patch_dir, patch_files):
for patch in patch_files:
if type(patch) is dict:
tmp = patch
patch = {}
for key in tmp.keys():
patch[os.path.join(patch_dir, key)] = tmp[key]
self.patches.append(patch)
else:
self.patches.append(os.path.join(patch_dir, patch))
def configure(self):
s = Subprocess(log=self.logfile, cwd=self.build_dir)
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
s.check_call("./configure --prefix=%s %s %s" % (self.install_dir, self.options.configure, self.configure_options))
def make(self):
jobs = self.options.jobs
make = ((jobs > 0 and 'make -j%s' % jobs) or 'make')
s = Subprocess(log=self.logfile, cwd=self.build_dir)
if self.options.force:
s.check_call(make)
else:
s.check_call(make)
s.check_call("make test")
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
s.check_call(make)
if not self.options.no_test:
if self.options.force:
# note: ignore tests failure error.
s.call("make test")
else:
s.check_call("make test")
def make_install(self):
version = self.pkg.version
if version == "1.5.2" or version == "1.6.1":
makedirs(self.install_dir)
s = Subprocess(log=self.logfile, cwd=self.build_dir)
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
s.check_call("make install")
def symlink(self):
@@ -149,7 +206,7 @@ class PythonInstaller(object):
options = self.options
pkgname = self.pkg.name
if options.no_setuptools:
logger.info("Skip installation setuptools.")
logger.info("Skip installation of setuptools.")
return
download_url = DISTRIBUTE_SETUP_DLSITE
filename = Link(download_url).filename
@@ -161,94 +218,79 @@ class PythonInstaller(object):
install_dir = os.path.join(PATH_PYTHONS, pkgname)
path_python = os.path.join(install_dir,"bin","python")
try:
s = Subprocess(log=self.logfile, cwd=PATH_DISTS)
s = Subprocess(log=self.logfile, cwd=PATH_DISTS, verbose=self.options.verbose)
logger.info("Installing distribute into %s" % install_dir)
s.check_call("%s %s" % (path_python, filename))
# Using easy_install install pip
s.check_call([path_python, filename])
# installing pip
easy_install = os.path.join(install_dir, 'bin', 'easy_install')
if os.path.isfile(easy_install):
logger.info("Installing pip into %s" % install_dir)
s.check_call("%s pip" % (easy_install))
s.check_call([easy_install, 'pip'])
except:
logger.error("Failed to install setuptools. See %s/build.log to see why." % (ROOT))
logger.info("Skip install setuptools.")
logger.info("Skip installation of setuptools.")
class PythonInstallerMacOSX(PythonInstaller):
"""Python installer for MacOSX SnowLeopard
"""Python installer for MacOSX
"""
def __init__(self, arg, options):
super(PythonInstallerMacOSX, self).__init__(arg, options)
version = self.pkg.version
# check for version
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)
raise NotSupportedVersionException
# 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'
elif is_python27(version):
self.configure_options = '--with-universal-archs="intel" --enable-universalsdk=/ MACOSX_DEPLOYMENT_TARGET=10.6'
else:
self.configure_options = '--with-universal-archs="intel" --enable-universalsdk=/ MACOSX_DEPLOYMENT_TARGET=10.6'
target = get_macosx_deployment_target()
if target:
self.configure_options = 'MACOSX_DEPLOYMENT_TARGET=%s' % target
# note: skip `make test` to avoid hanging test_threading.
if is_python25(version) or is_python24(version):
self.options.no_test = True
def patch(self):
# note: want an interface to the source patching functionality. like a patchperl.
version = self.pkg.version
try:
s = Subprocess(log=self.logfile, cwd=self.build_dir)
patches = []
eds = {}
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-gestaltmodule.c.diff']
eds = {'_localemodule.c.ed': 'Modules/_localemodule.c',
'locale.py.ed': 'Lib/locale.py'}
elif is_python26(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON26
patches = ['patch-Lib-cgi.py.diff',
'patch-Lib-distutils-dist.py.diff',
'patch-Mac-IDLE-Makefile.in.diff',
'patch-Mac-Makefile.in.diff',
'patch-Mac-PythonLauncher-Makefile.in.diff',
'patch-Mac-Tools-Doc-setup.py.diff',
'patch-setup.py-db46.diff',
'patch-Lib-ctypes-macholib-dyld.py.diff',
'patch-setup_no_tkinter.py.diff']
eds = {'_localemodule.c.ed': 'Modules/_localemodule.c',
'locale.py.ed': 'Lib/locale.py'}
elif is_python27(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON27
patches = ['patch-Modules-posixmodule.diff']
if patches or eds:
logger.info("Patching %s" % self.pkg.name)
for patch in patches:
s.check_call("patch -p0 < %s" % os.path.join(patch_dir, patch))
for (ed, source) in eds.items():
ed = os.path.join(patch_dir, ed)
s.check_call('ed - %s < %s' % (source, ed))
except:
logger.error("Failed to patch `%s`" % self.build_dir)
sys.exit(1)
if is_python24(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON24
self._add_patches_to_list(patch_dir, ['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
self._add_patches_to_list(patch_dir, ['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-gestaltmodule.c.diff',
{'_localemodule.c.ed': 'Modules/_localemodule.c'},
{'locale.py.ed': 'Lib/locale.py'}])
elif is_python26(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON26
self._add_patches_to_list(patch_dir, ['patch-Lib-cgi.py.diff',
'patch-Lib-distutils-dist.py.diff',
'patch-Mac-IDLE-Makefile.in.diff',
'patch-Mac-Makefile.in.diff',
'patch-Mac-PythonLauncher-Makefile.in.diff',
'patch-Mac-Tools-Doc-setup.py.diff',
'patch-setup.py-db46.diff',
'patch-Lib-ctypes-macholib-dyld.py.diff',
'patch-setup_no_tkinter.py.diff',
{'_localemodule.c.ed': 'Modules/_localemodule.c'},
{'locale.py.ed': 'Lib/locale.py'}])
elif is_python27(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON27
self._add_patches_to_list(patch_dir, ['patch-Modules-posixmodule.diff'])
self._do_patch()
@@ -0,0 +1,47 @@
# HG changeset patch
# User Barry Warsaw <barry@python.org>
# Date 1302190091 14400
# Node ID bd0f73a9538e05f526feaf05821e68bdcff498fa
# Parent 2e4cdaffe493e879fb5367a4aa454491de451137
Backport for Python 2.7 of issue 11715 support for building Python on
multiarch Debian/Ubuntu.
diff --git a/setup.py b/setup.py
--- setup.py.orig
+++ setup.py
@@ -345,10 +345,33 @@ class PyBuildExt(build_ext):
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,45 @@
--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900
+++ setup.py 2011-07-07 19:25:04.548416377 +0900
@@ -13,6 +13,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -242,10 +243,34 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ fp = open(tmpfile)
+ multiarch_path_component = fp.readline().strip()
+ fp.close()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,45 @@
--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900
+++ setup.py 2011-07-07 19:25:04.548416377 +0900
@@ -13,6 +13,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -242,10 +243,34 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ fp = open(tmpfile)
+ multiarch_path_component = fp.readline().strip()
+ fp.close()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,44 @@
--- setup.py.orig 2011-07-07 19:41:48.610196111 +0900
+++ setup.py 2011-07-07 19:46:44.986310031 +0900
@@ -14,6 +14,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -308,10 +309,33 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,38 @@
--- setup.py.orig 2011-07-07 20:26:15.000000000 +0900
+++ setup.py 2011-07-07 20:29:28.735543350 +0900
@@ -370,12 +370,35 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used, but the local build
# directories (i.e. '.' and 'Include') must be first. See issue
# 10520.
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
+84 -43
View File
@@ -1,17 +1,17 @@
import os
import sys
import errno
import shutil
import subprocess
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
import subprocess
import shlex
from pythonbrew.define import PATH_BIN, PATH_ETC_CURRENT
from pythonbrew.exceptions import ShellCommandException
from pythonbrew.log import logger
import sys
def size_format(b):
kb = 1000
@@ -61,9 +61,15 @@ def is_gzip(content_type, filename):
return True
return False
def is_macosx_snowleopard():
def is_macosx():
mac_ver = platform.mac_ver()[0]
return mac_ver >= '10.6' and mac_ver < '10.7'
return mac_ver >= '10.6'
def get_macosx_deployment_target():
m = re.search('^([0-9]+\.[0-9]+)', platform.mac_ver()[0])
if m:
return m.group(1)
return None
def is_python24(version):
return version >= '2.4' and version < '2.5'
@@ -77,6 +83,15 @@ def is_python26(version):
def is_python27(version):
return version >= '2.7' and version < '2.8'
def is_python30(version):
return version >= '3.0' and version < '3.1'
def is_python31(version):
return version >= '3.1' and version < '3.2'
def is_python32(version):
return version >= '3.2' and version < '3.3'
def makedirs(path):
try:
os.makedirs(path)
@@ -107,12 +122,6 @@ def rm_r(path):
unlink(path)
def off():
for root, dirs, files in os.walk(PATH_BIN):
for f in files:
if f == "pythonbrew" or f == "pybrew":
continue
unlink("%s/%s" % (root, f))
unlink("%s/current" % PATH_PYTHONS)
set_current_path(PATH_BIN)
def split_leading_dir(path):
@@ -142,7 +151,7 @@ def has_leading_dir(paths):
def untar_file(filename, location):
if not os.path.exists(location):
makedirs(location)
os.makedirs(location)
if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
mode = 'r:gz'
elif filename.lower().endswith('.bz2') or filename.lower().endswith('.tbz'):
@@ -186,12 +195,15 @@ def untar_file(filename, location):
shutil.copyfileobj(fp, destfp)
finally:
destfp.close()
os.chmod(path, member.mode)
fp.close()
# note: configure ...etc
os.chmod(path, member.mode)
# note: the file timestamps should be such that asdl_c.py is not invoked.
os.utime(path, (member.mtime, member.mtime))
finally:
tar.close()
def unpack_downloadfile(content_type, download_file, target_dir):
def extract_downloadfile(content_type, download_file, target_dir):
logger.info("Extracting %s into %s" % (os.path.basename(download_file), target_dir))
if is_gzip(content_type, download_file):
untar_file(download_file, target_dir)
@@ -201,12 +213,10 @@ def unpack_downloadfile(content_type, download_file, target_dir):
return True
def get_current_python_path():
p = Popen('command -v python', stdout=PIPE, shell=True)
p.wait()
if p.returncode == 0:
return p.stdout.read().strip()
else:
return None
"""return: python path or ''
"""
p = subprocess.Popen('command -v python', stdout=subprocess.PIPE, shell=True)
return to_str(p.communicate()[0].strip())
def set_current_path(path):
fp = open(PATH_ETC_CURRENT, 'w')
@@ -225,40 +235,71 @@ def fileurl_to_path(url):
url = '/' + url[len('file:'):].lstrip('/')
return urllib.unquote(url)
def u(val):
"""to unicode
"""
def to_str(val):
try:
# for python3
if type(val) == bytes:
# python3
if type(val) is bytes:
return val.decode()
except:
if type(val) == str:
return val.decode("utf-8")
return val
if type(val) is unicode:
return val.encode("utf-8")
return val
def is_str(val):
try:
# python2
return isinstance(val, basestring)
except:
# python3
return isinstance(val, str)
return False
class Subprocess(object):
def __init__(self, log=None, shell=True, cwd=None, print_cmd=False):
def __init__(self, log=None, cwd=None, verbose=False, debug=False):
self._log = log
self._shell = shell
self._cwd = cwd
self._print_cmd = print_cmd
self._verbose = verbose
self._debug = debug
def chdir(self, cwd):
self._cwd = cwd
def check_call(self, cmd, shell=None, cwd=None):
if shell:
self._shell = shell
if cwd:
self._cwd = cwd
if self._print_cmd:
def shell(self, cmd):
if self._debug:
logger.info(cmd)
if self._log:
cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log)
retcode = subprocess.call(cmd, shell=self._shell, cwd=self._cwd)
if retcode != 0:
raise ShellCommandException('Failed to `%s` command' % cmd)
if self._verbose:
cmd = "(%s) 2>&1 | tee '%s'" % (cmd, self._log)
else:
cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log)
returncode = subprocess.call(cmd, shell=True, cwd=self._cwd)
if returncode:
raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd))
def call(self, cmd):
if is_str(cmd):
cmd = shlex.split(cmd)
if self._debug:
logger.info(cmd)
fp = ((self._log and open(self._log, 'a')) or None)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self._cwd)
while p.returncode is None:
p.poll()
line = to_str(p.stdout.readline())
if self._verbose:
logger.info(line.strip())
if fp:
fp.write(line)
fp.flush()
if fp:
fp.close()
return p.returncode
def check_call(self, cmd):
returncode = self.call(cmd)
if returncode:
raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd))
class Package(object):
def __init__(self, name, alias=None):
@@ -293,7 +334,7 @@ class Link(object):
return name
@property
def show_msg(self):
def base_url(self):
return posixpath.basename(self._url.split('#', 1)[0].split('?', 1)[0])
+1 -1
View File
@@ -1 +1 @@
0.7.3
0.8
+3 -2
View File
@@ -1,5 +1,6 @@
class UpdateOptions(object):
head = False
master = False
develop = False
config = False
force = False
@@ -7,4 +8,4 @@ def test_update():
from pythonbrew.commands.update import UpdateCommand
c = UpdateCommand()
c.run_command(UpdateOptions(), None)
+2
View File
@@ -2,6 +2,8 @@ from tests import TESTPY_VERSION
class InstallOptions(object):
force = True
no_test = True
verbose = False
configure = ""
no_setuptools = False
alias = None
-4
View File
@@ -1,4 +0,0 @@
def test_clean():
from pythonbrew.commands.clean import CleanCommand
c = CleanCommand()
c.run_command(None, None)
+4
View File
@@ -0,0 +1,4 @@
def test_clean():
from pythonbrew.commands.cleanup import CleanupCommand
c = CleanupCommand()
c.run_command(None, None)