mirror of
https://github.com/kennethreitz-archive/python-build.git
synced 2026-06-05 15:20:16 +00:00
release 0.8
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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
@@ -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
|
||||
=======
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -1 +1 @@
|
||||
0.7.3
|
||||
0.8
|
||||
@@ -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,6 +2,8 @@ from tests import TESTPY_VERSION
|
||||
|
||||
class InstallOptions(object):
|
||||
force = True
|
||||
no_test = True
|
||||
verbose = False
|
||||
configure = ""
|
||||
no_setuptools = False
|
||||
alias = None
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
def test_clean():
|
||||
from pythonbrew.commands.clean import CleanCommand
|
||||
c = CleanCommand()
|
||||
c.run_command(None, None)
|
||||
@@ -0,0 +1,4 @@
|
||||
def test_clean():
|
||||
from pythonbrew.commands.cleanup import CleanupCommand
|
||||
c = CleanupCommand()
|
||||
c.run_command(None, None)
|
||||
Reference in New Issue
Block a user