diff --git a/ChangeLog b/ChangeLog index f61a9d6..d44a530 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* 0.10 + - Added systemwide install support. (issue #31) + - Fixed issue #41 Handle venv binary with the symlink command. + - Improved `venv` command (without virtualenvwrapper) + * 0.9 - Added `buildout` command. - Added `venv` command. diff --git a/PKG-INFO b/PKG-INFO index 8276229..3369289 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -25,6 +25,17 @@ If you need to install pythonbrew into somewhere else, you can do that by settin chmod +x pythonbrewinstall ./pythonbrewinstall +For Systemwide(Multi-User) installation +--------------------------------------- + +If the install script is run as root, pythonbrew will automatically install into /usr/local/pythonbrew. + +The pythonbrew will be automatically configured for every user on the system if you install as root. + +After installation, where you would normally use `sudo`, non-root users will need to use `sudopybrew`:: + + sudopybrew install -n -v -j2 2.7.2 + Usage ===== @@ -91,14 +102,16 @@ Create/Remove a symbolic link to python (in a directory on your $PATH):: 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 + pythonbrew symlink -v foo # Create a symbolic link to the specified virtual environment python in bin directory Runs the buildout with specified or current using python:: pythonbrew buildout pythonbrew buildout -p 2.6.6 -Create isolated python environments (uses virtualenv and virtualenvwrapper):: +Create isolated python environments (uses virtualenv):: + pythonbrew venv init pythonbrew venv create proj pythonbrew venv list pythonbrew venv use proj @@ -149,7 +162,7 @@ buildout Runs the buildout with specified or current using python. venv - Create isolated python environments (uses virtualenv and virtualenvwrapper) + Create isolated python environments (uses virtualenv) version Show version. @@ -160,11 +173,18 @@ See more details below Changelog ========= +0.10 (2011-08-08) +----------------- + +- Added systemwide install support. (issue #31) +- Fixed issue #41 Handle venv binary with the symlink command. +- Improved `venv` command (without virtualenvwrapper) + 0.9 (2011-07-21) ---------------- -- Add `venv` command (virtualenv and virtualenvwrapper supported) -- Add `buildout` command. +- Added `venv` command (uses virtualenv and virtualenvwrapper) +- Added `buildout` command. 0.8 (2011-07-10) ---------------- diff --git a/README.rst b/README.rst index 68e9b7b..8c5cb50 100644 --- a/README.rst +++ b/README.rst @@ -25,6 +25,17 @@ If you need to install pythonbrew into somewhere else, you can do that by settin chmod +x pythonbrewinstall ./pythonbrewinstall +For Systemwide(Multi-User) installation +--------------------------------------- + +If the install script is run as root, pythonbrew will automatically install into /usr/local/pythonbrew. + +The pythonbrew will be automatically configured for every user on the system if you install as root. + +After installation, where you would normally use `sudo`, non-root users will need to use `sudopybrew`:: + + sudopybrew install -n -v -j2 2.7.2 + Usage ===== @@ -91,14 +102,16 @@ Create/Remove a symbolic link to python (in a directory on your $PATH):: 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 + pythonbrew symlink -v foo # Create a symbolic link to the specified virtual environment python in bin directory Runs the buildout with specified or current using python:: pythonbrew buildout pythonbrew buildout -p 2.6.6 -Create isolated python environments (uses virtualenv and virtualenvwrapper):: +Create isolated python environments (uses virtualenv):: + pythonbrew venv init pythonbrew venv create proj pythonbrew venv list pythonbrew venv use proj @@ -149,7 +162,7 @@ buildout Runs the buildout with specified or current using python. venv - Create isolated python environments (uses virtualenv and virtualenvwrapper) + Create isolated python environments (uses virtualenv) version Show version. diff --git a/pythonbrew-install b/pythonbrew-install index f918d47..70594c1 100755 --- a/pythonbrew-install +++ b/pythonbrew-install @@ -66,16 +66,23 @@ if [[ $PYTHON_FOUND != '1' ]] ; then exit fi -ROOT="$HOME/.pythonbrew" -if [[ -n $PYTHONBREW_ROOT ]] ; then - ROOT=$PYTHONBREW_ROOT +systemwide_install=0 +if [[ -n "$PYTHONBREW_ROOT" ]] ; then + ROOT="$PYTHONBREW_ROOT" +else + if (( UID == 0 )) ; then + systemwide_install=1 + ROOT="/usr/local/pythonbrew" + else + ROOT="$HOME/.pythonbrew" + fi fi PATH_DISTS="$ROOT/dists" STABLE_VERSION=`curl -skL https://github.com/utahta/pythonbrew/raw/master/stable-version.txt` STABLE_VERSION=`trim $STABLE_VERSION` -if [[ $STABLE_VERSION = "" ]] ; then - echo 'Could not get stable-version of pythonbrew.' +if [[ -z "$STABLE_VERSION" ]] ; then + echo 'Can not get stable-version of pythonbrew.' exit 1 fi TEMP_FILE="pythonbrew-$STABLE_VERSION" @@ -93,7 +100,11 @@ echo "Extracting $PATH_DISTS/$TEMP_TARBALL" builtin cd $PATH_DISTS ; tar zxf $TEMP_TARBALL echo "Installing pythonbrew into $ROOT" -$PYTHON $PATH_DISTS/$TEMP_FILE/pythonbrew_install.py +if (( systemwide_install == 1 )) ; then + PYTHONBREW_ROOT="$ROOT" $PYTHON $PATH_DISTS/$TEMP_FILE/pythonbrew_install.py --systemwide +else + $PYTHON $PATH_DISTS/$TEMP_FILE/pythonbrew_install.py +fi if [[ $? == 1 ]] ; then echo "Failed to install pythonbrew." exit diff --git a/pythonbrew/__init__.py b/pythonbrew/__init__.py index e09793c..9eec705 100644 --- a/pythonbrew/__init__.py +++ b/pythonbrew/__init__.py @@ -1,7 +1,14 @@ import sys +import os from pythonbrew.basecommand import command_dict, load_all_commands from pythonbrew.baseparser import parser from pythonbrew.log import logger +from pythonbrew.define import PATH_HOME_ETC +from pythonbrew.util import makedirs + +def init_home(): + if not os.path.isdir(PATH_HOME_ETC): + makedirs(PATH_HOME_ETC) def main(): options, args = parser.parse_args(sys.argv[1:]) @@ -10,13 +17,10 @@ def main(): if not args: args = ['help'] # as default + init_home() 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] diff --git a/pythonbrew/commands/buildout.py b/pythonbrew/commands/buildout.py index 81ef50a..1c29574 100644 --- a/pythonbrew/commands/buildout.py +++ b/pythonbrew/commands/buildout.py @@ -2,7 +2,7 @@ import os import sys import subprocess from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, BOOTSTRAP_DLSITE, PATH_DISTS +from pythonbrew.define import PATH_PYTHONS, BOOTSTRAP_DLSITE from pythonbrew.util import Package, get_using_python_pkgname, Link, is_installed from pythonbrew.log import logger from pythonbrew.downloader import Downloader @@ -28,7 +28,7 @@ class BuildoutCommand(Command): else: pkgname = get_using_python_pkgname() if not is_installed(pkgname): - logger.info('%s is not installed.' % pkgname) + logger.error('`%s` is not installed.' % pkgname) sys.exit(1) logger.info('Using %s' % pkgname) @@ -38,20 +38,21 @@ class BuildoutCommand(Command): # Download bootstrap.py download_url = BOOTSTRAP_DLSITE filename = Link(download_url).filename - bootstrap = os.path.join(PATH_DISTS, filename) + bootstrap = os.path.join(os.getcwd(), filename) # fetching into current directory try: d = Downloader() d.download(filename, download_url, bootstrap) except: - logger.error("Failed to download. `%s`" % download_url) + e = sys.exc_info()[1] + logger.error("%s" % (e)) sys.exit(1) - # Using bootstrap.py + # call bootstrap.py if subprocess.call([python, bootstrap, '-d']): logger.error('Failed to bootstrap.') sys.exit(1) - # Using buildout + # call buildout subprocess.call(['./bin/buildout']) BuildoutCommand() diff --git a/pythonbrew/commands/help.py b/pythonbrew/commands/help.py index 7256ae4..7e9d8a3 100644 --- a/pythonbrew/commands/help.py +++ b/pythonbrew/commands/help.py @@ -17,11 +17,11 @@ class HelpCommand(Command): command.parser.print_help() return parser.print_help() - logger.info("\nCommands available:") + logger.log("\nCommands available:") commands = [command_dict[key] for key in sorted(command_dict.keys())] for command in commands: - logger.info(" %s: %s" % (command.name, command.summary)) - logger.info("\nFurther Instructions:") - logger.info(" https://github.com/utahta/pythonbrew") + logger.log(" %s: %s" % (command.name, command.summary)) + logger.log("\nFurther Instructions:") + logger.log(" https://github.com/utahta/pythonbrew") HelpCommand() diff --git a/pythonbrew/commands/install.py b/pythonbrew/commands/install.py index 34e6877..2a67c2c 100644 --- a/pythonbrew/commands/install.py +++ b/pythonbrew/commands/install.py @@ -1,5 +1,5 @@ +import sys from pythonbrew.basecommand import Command -from pythonbrew.log import logger from pythonbrew.installer.pythoninstaller import PythonInstaller,\ PythonInstallerMacOSX from pythonbrew.util import is_macosx @@ -63,22 +63,22 @@ class InstallCommand(Command): ) def run_command(self, options, args): - if args: - # installing python - for arg in args: - try: - if is_macosx(): - p = PythonInstallerMacOSX(arg, options) - else: - p = PythonInstaller(arg, options) - p.install() - except UnknownVersionException: - continue - except AlreadyInstalledException: - continue - except NotSupportedVersionException: - continue - else: - logger.info("Unknown python version.") + if not args: + self.parser.print_help() + sys.exit(1) + # installing python + for arg in args: + try: + if is_macosx(): + p = PythonInstallerMacOSX(arg, options) + else: + p = PythonInstaller(arg, options) + p.install() + except UnknownVersionException: + continue + except AlreadyInstalledException: + continue + except NotSupportedVersionException: + continue InstallCommand() diff --git a/pythonbrew/commands/list.py b/pythonbrew/commands/list.py index d9fb902..91dfa6f 100644 --- a/pythonbrew/commands/list.py +++ b/pythonbrew/commands/list.py @@ -3,8 +3,7 @@ import re from pythonbrew.basecommand import Command from pythonbrew.define import PYTHON_VERSION_URL, LATEST_VERSIONS_OF_PYTHON,\ PATH_PYTHONS -from pythonbrew.util import Package, get_using_python_pkgname,\ - get_using_python_path +from pythonbrew.util import Package, get_using_python_pkgname from pythonbrew.log import logger class ListCommand(Command): @@ -36,18 +35,16 @@ class ListCommand(Command): self.installed(options, args) def installed(self, options, args): - logger.info('# installed pythons') + logger.log("# pythonbrew pythons") cur = get_using_python_pkgname() for d in sorted(os.listdir(PATH_PYTHONS)): if cur and cur == d: - logger.info('%s (*)' % d) + logger.log(' %s (*)' % d) else: - logger.info('%s' % d) - if not cur: - logger.info('%s (*)' % get_using_python_path()) + logger.log(' %s' % d) def available_install(self, options, args): - logger.info('# available install pythons') + logger.log('# Pythons') if args: pkg = Package(args[0]) _re = re.compile(r"%s" % pkg.name) @@ -57,12 +54,12 @@ class ListCommand(Command): pkgs.append(pkgname) if pkgs: for pkgname in pkgs: - logger.info("%s" % pkgname) + logger.log("%s" % pkgname) else: - logger.info("Python version not found. `%s`" % pkg.name) + logger.error("`%s` was not found." % pkg.name) else: for pkgname in self._get_packages_name(options): - logger.info("%s" % pkgname) + logger.log("%s" % pkgname) def _get_packages_name(self, options): return ["Python-%s" % version for version in sorted(PYTHON_VERSION_URL.keys()) diff --git a/pythonbrew/commands/py.py b/pythonbrew/commands/py.py index 9390dca..102cb79 100644 --- a/pythonbrew/commands/py.py +++ b/pythonbrew/commands/py.py @@ -32,12 +32,12 @@ class PyCommand(Command): def run_command(self, options, args): if not args: - logger.info("Unrecognized command line argument: argument not found.") + self.parser.print_help() sys.exit(1) pythons = self._get_pythons(options.pythons) for d in pythons: if options.verbose: - logger.info('*** %s ***' % d) + logger.info('`%s` running...' % d) path = os.path.join(PATH_PYTHONS, d, 'bin', args[0]) if os.path.isfile(path) and os.access(path, os.X_OK): subprocess.call([path] + args[1:]) @@ -46,7 +46,7 @@ class PyCommand(Command): if os.path.isfile(path) and os.access(path, os.X_OK): subprocess.call([path] + args) else: - logger.info('%s: No such file or directory.' % path) + logger.error('%s: No such file or directory.' % path) def _get_pythons(self, _pythons): pythons = [Package(p).name for p in _pythons] diff --git a/pythonbrew/commands/switch.py b/pythonbrew/commands/switch.py index d25e5c5..34e25be 100644 --- a/pythonbrew/commands/switch.py +++ b/pythonbrew/commands/switch.py @@ -1,7 +1,7 @@ import os import sys from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, PATH_BIN +from pythonbrew.define import PATH_PYTHONS from pythonbrew.util import Package, set_current_path, is_installed from pythonbrew.log import logger @@ -12,16 +12,16 @@ class SwitchCommand(Command): def run_command(self, options, args): if not args: - logger.info("Unrecognized command line argument: argument not found.") + self.parser.print_help() sys.exit(1) pkg = Package(args[0]) pkgname = pkg.name if not is_installed(pkgname): - logger.info("`%s` is not installed." % pkgname) + logger.error("`%s` is not installed." % pkgname) sys.exit(1) pkgbin = os.path.join(PATH_PYTHONS,pkgname,'bin') - set_current_path('%s:%s' % (PATH_BIN, pkgbin)) + set_current_path(pkgbin) logger.info("Switched to %s" % pkgname) diff --git a/pythonbrew/commands/symlink.py b/pythonbrew/commands/symlink.py index 5e35d72..f87da05 100644 --- a/pythonbrew/commands/symlink.py +++ b/pythonbrew/commands/symlink.py @@ -1,7 +1,9 @@ import os +import sys from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, PATH_BIN -from pythonbrew.util import Package, symlink, unlink +from pythonbrew.define import PATH_PYTHONS, PATH_BIN, PATH_VENVS +from pythonbrew.util import Package, symlink, unlink, get_using_python_pkgname,\ + is_installed from pythonbrew.log import logger class SymlinkCommand(Command): @@ -32,6 +34,12 @@ class SymlinkCommand(Command): default=None, help="Use as default the specified python version." ) + self.parser.add_option( + "-v", "--venv", + dest="venv", + default=None, + help="Use the virtual environment python." + ) def run_command(self, options, args): if options.default: @@ -43,6 +51,28 @@ class SymlinkCommand(Command): self._symlink(bin, bin, pkgname) else: self._symlink('python', 'py', pkgname) + elif options.venv: + if options.pythons: + pkgname = Package(options.pythons[0]).name + else: + pkgname = get_using_python_pkgname() + if not is_installed(pkgname): + logger.error('`%s` is not installed.') + sys.exit(1) + + venv_pkgdir = os.path.join(PATH_VENVS, pkgname) + venv_dir = os.path.join(venv_pkgdir, options.venv) + if not os.path.isdir(venv_dir): + logger.error("`%s` environment was not found in %s." % (options.venv, venv_pkgdir)) + sys.exit(1) + pkg = Package(pkgname) + if args: + bin = args[0] + dstbin = '%s%s-%s' % (bin, pkg.version, options.venv) + self._symlink(bin, dstbin, pkgname) + else: + dstbin = 'py%s-%s' % (pkg.version, options.venv) + self._symlink('python', dstbin, pkgname) else: pythons = self._get_pythons(options.pythons) for pkgname in pythons: @@ -75,7 +105,7 @@ class SymlinkCommand(Command): if os.path.isfile(src): symlink(src, dst) else: - logger.info("%s: File not found" % src) + logger.error("%s was not found in your path." % src) def _get_pythons(self, _pythons): """Get the installed python versions list. diff --git a/pythonbrew/commands/uninstall.py b/pythonbrew/commands/uninstall.py index d04e53c..0699224 100644 --- a/pythonbrew/commands/uninstall.py +++ b/pythonbrew/commands/uninstall.py @@ -19,7 +19,7 @@ class UninstallCommand(Command): pkgpath = os.path.join(PATH_PYTHONS, pkgname) venvpath = os.path.join(PATH_VENVS, pkgname) if not is_installed(pkgname): - logger.info("`%s` is not installed." % pkgname) + logger.error("`%s` is not installed." % pkgname) continue if get_using_python_pkgname() == pkgname: off() diff --git a/pythonbrew/commands/update.py b/pythonbrew/commands/update.py index f9d760a..6a3e4a4 100644 --- a/pythonbrew/commands/update.py +++ b/pythonbrew/commands/update.py @@ -65,7 +65,7 @@ class UpdateCommand(Command): except: logger.error("Failed to download. `%s`" % download_url) sys.exit(1) - logger.info("The config.cfg has been updated.") + logger.log("The config.cfg has been updated.") def _update_pythonbrew(self, options, args): if options.master: @@ -81,7 +81,7 @@ class UpdateCommand(Command): download_url = get_pythonbrew_update_url(version) if not download_url: - logger.error("`%s` of pythonbrew not found." % version) + logger.error("`pythonbrew-%s` was not found in pypi." % version) sys.exit(1) headinfo = get_headerinfo_from_url(download_url) content_type = headinfo['content-type'] diff --git a/pythonbrew/commands/use.py b/pythonbrew/commands/use.py index 0b7c200..be1ea86 100644 --- a/pythonbrew/commands/use.py +++ b/pythonbrew/commands/use.py @@ -1,7 +1,7 @@ import os import sys from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, PATH_BIN, PATH_ETC_TEMP +from pythonbrew.define import PATH_PYTHONS, PATH_HOME_ETC_TEMP from pythonbrew.util import Package from pythonbrew.log import logger @@ -12,24 +12,23 @@ class UseCommand(Command): def run_command(self, options, args): if not args: - logger.info("Unrecognized command line argument: argument not found.") + self.parser.print_help() sys.exit(1) pkg = Package(args[0]) pkgname = pkg.name pkgdir = os.path.join(PATH_PYTHONS, pkgname) if not os.path.isdir(pkgdir): - logger.info("`%s` is not installed." % pkgname) + logger.error("`%s` is not installed." % pkgname) sys.exit(1) pkgbin = os.path.join(pkgdir,'bin') - self._set_temp('%s:%s' % (PATH_BIN, pkgbin)) + self._set_temp(pkgbin) logger.info("Using `%s`" % pkgname) def _set_temp(self, path): - fp = open(PATH_ETC_TEMP, 'w') - fp.write('PATH_PYTHONBREW="%s"\n' % (path)) + fp = open(PATH_HOME_ETC_TEMP, 'w') + fp.write('PATH_PYTHONBREW_TEMP="%s"\n' % (path)) fp.close() - UseCommand() diff --git a/pythonbrew/commands/venv.py b/pythonbrew/commands/venv.py index 8ac4e4f..00ea77c 100644 --- a/pythonbrew/commands/venv.py +++ b/pythonbrew/commands/venv.py @@ -1,10 +1,13 @@ import os import sys from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, PATH_VENVS, PATH_ETC_VENV -from pythonbrew.util import Subprocess, Package,\ - is_installed, get_installed_pythons_pkgname, get_using_python_pkgname +from pythonbrew.define import PATH_PYTHONS, PATH_VENVS, PATH_HOME_ETC_VENV,\ + PATH_ETC, VIRTUALENV_DLSITE, PATH_DISTS +from pythonbrew.util import Package, \ + is_installed, get_installed_pythons_pkgname, get_using_python_pkgname,\ + untar_file, Subprocess, rm_r from pythonbrew.log import logger +from pythonbrew.downloader import Downloader class VenvCommand(Command): name = "venv" @@ -26,38 +29,30 @@ class VenvCommand(Command): action='store_true', default=False, help="Show the all python environments.", - metavar='VERSION' ) - self.template_env = """export VIRTUALENVWRAPPER_PYTHON=%(venv_py)s -export VIRTUALENVWRAPPER_VIRTUALENV=%(venv_venv)s -export WORKON_HOME=%(workon_home)s -export VIRTUALENVWRAPPER_HOOK_DIR=%(workon_home)s -export VIRTUALENVWRAPPER_LOG_DIR=%(workon_home)s -source %(venv_sh)s -""" - + self.parser.add_option( + "-n", "--no-site-packages", + dest="no_site_packages", + action='store_true', + default=False, + help="Don't give access to the global site-packages dir to the virtual environment.", + ) + self._venv_dir = os.path.join(PATH_ETC, 'virtualenv') + self._venv = os.path.join(self._venv_dir, 'virtualenv.py') + def run_command(self, options, args): if not args: - logger.error('Unrecognized command line argument: ( see: \'pythonbrew help venv\' )') + self.parser.print_help() sys.exit(1) cmd = args[0] - if not cmd in ('create', 'delete', 'use', 'list'): - logger.error('Unrecognized command line argument: ( see: \'pythonbrew help venv\' )') + if not cmd in ('init', 'create', 'delete', 'use', 'list'): + self.parser.print_help() sys.exit(1) - # find python2 - venv_pkgname = None - for pkgname in reversed(get_installed_pythons_pkgname()): - # virtualenvwrapper require Python2 - venv_pkgver = Package(pkgname).version - if venv_pkgver >= '2.4' and venv_pkgver < '3': - venv_pkgname = pkgname - break - if not venv_pkgname: - logger.error('Can not create virtual environment before installing a python2. Try \'pythonbrew install \'.') - sys.exit(1) - venv_dir = os.path.join(PATH_PYTHONS, venv_pkgname) - venv_bin = os.path.join(venv_dir, 'bin') + # initialize? + if cmd == 'init': + self.run_command_init() + return # target python interpreter if options.python: @@ -66,92 +61,103 @@ source %(venv_sh)s logger.error('%s is not installed.' % pkgname) sys.exit(1) else: + # check using python under pythonbrew pkgname = get_using_python_pkgname() if not pkgname: - logger.error('Can not use venv command before using a python. Try \'pythonbrew switch \'.') + logger.error('Can not use venv command before switching a python. Try \'pythonbrew switch \'.') sys.exit(1) self._pkgname = pkgname self._target_py = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python') self._workon_home = os.path.join(PATH_VENVS, pkgname) - self._venv_py = os.path.join(venv_bin, 'python') - self._venv_venv = os.path.join(venv_bin, 'virtualenv') - self._venv_sh = os.path.join(venv_bin, 'virtualenvwrapper.sh') + self._py = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python') - # has virtualenv & virtualenvwrapper? - if not self._venv_venv or not self._venv_sh: - logger.info('Installing virtualenv into %s' % venv_dir) - s = Subprocess(verbose=True) - s.shell('%s %s %s' % (os.path.join(venv_bin,'pip'), 'install', 'virtualenvwrapper')) + # is already installed virtualenv? + if not os.path.exists(self._venv): + self.run_command_init() # Create a shell script - try: - self.__getattribute__('run_command_%s' % cmd)(options, args) - except: - logger.error('`%s` command not found.' % cmd) + self.__getattribute__('run_command_%s' % cmd)(options, args) + + def run_command_init(self): + if os.path.exists(self._venv): + logger.info('venv command is already initialized.') + return + if not os.access(PATH_DISTS, os.W_OK): + logger.error("Can not initialize venv command: Permission denied.") sys.exit(1) + d = Downloader() + download_file = os.path.join(PATH_DISTS, 'virtualenv.tar.gz') + d.download('virtualenv.tar.gz', VIRTUALENV_DLSITE, download_file) + logger.info('Extracting virtualenv into %s' % self._venv_dir) + untar_file(download_file, self._venv_dir) def run_command_create(self, options, args): - output = [self.template_env % {'venv_py': self._venv_py, - 'venv_venv': self._venv_venv, - 'workon_home': self._workon_home, - 'venv_sh': self._venv_sh}] + if not os.access(PATH_VENVS, os.W_OK): + logger.error("Can not create a virtuale environment in %s.\nPermission denied." % PATH_VENVS) + sys.exit(1) + + virtualenv_options = [] + if options.no_site_packages: + virtualenv_options.append('--no-site-packages') + for arg in args[1:]: - output.append("""echo '# Create `%(arg)s` environment into %(workon_home)s' -mkvirtualenv -p '%(target_py)s' '%(arg)s' -""" % {'arg': arg, - 'workon_home': self._workon_home, - 'target_py': self._target_py}) - self._write(''.join(output)) + target_dir = os.path.join(self._workon_home, arg) + logger.info("Creating `%s` environment into %s" % (arg, self._workon_home)) + # make command + cmd = [self._py, self._venv, '-p', self._target_py] + cmd.extend(virtualenv_options) + cmd.append(target_dir) + # create environment + s = Subprocess(verbose=True) + s.call(cmd) def run_command_delete(self, options, args): - output = [self.template_env % {'venv_py': self._venv_py, - 'venv_venv': self._venv_venv, - 'workon_home': self._workon_home, - 'venv_sh': self._venv_sh}] for arg in args[1:]: - output.append("""echo '# Delete `%(arg)s` environment in %(workon_home)s' -rmvirtualenv '%(arg)s' -""" % {'arg': arg, - 'workon_home': self._workon_home}) - self._write(''.join(output)) + target_dir = os.path.join(self._workon_home, arg) + if not os.path.isdir(target_dir): + logger.error('%s already does not exist.' % target_dir) + else: + if not os.access(target_dir, os.W_OK): + logger.error("Can not delete %s.\nPermission denied." % target_dir) + continue + logger.info('Deleting `%s` environment in %s' % (arg, self._workon_home)) + # make command + rm_r(target_dir) def run_command_use(self, options, args): if len(args) < 2: logger.error("Unrecognized command line argument: ( 'pythonbrew venv use ' )") sys.exit(1) - template = self.template_env + """echo '# Using `%(arg)s` environment (found in %(workon_home)s)' + + activate = os.path.join(self._workon_home, args[1], 'bin', 'activate') + if not os.path.exists(activate): + logger.error('`%s` environment already does not exist. Try `pythonbrew venv create %s`.' % (args[1], args[1])) + sys.exit(1) + + self._write("""\ +echo '# Using `%(arg)s` environment (found in %(workon_home)s)' echo '# To leave an environment, simply run `deactivate`' -workon '%(arg)s' -""" - self._write(template % {'venv_py': self._venv_py, - 'venv_venv': self._venv_venv, - 'workon_home': self._workon_home, - 'venv_sh': self._venv_sh, - 'arg': args[1]}) - +source '%(activate)s' +""" % {'arg': args[1], 'workon_home': self._workon_home, 'activate': activate}) + def run_command_list(self, options, args): - template = self.template_env + """echo '# virtualenv for %(pkgname)s (found in %(workon_home)s)' -workon -""" if options.all: - output = [] for pkgname in get_installed_pythons_pkgname(): workon_home = os.path.join(PATH_VENVS, pkgname) - output.append(template % {'venv_py': self._venv_py, - 'venv_venv': self._venv_venv, - 'workon_home': workon_home, - 'venv_sh': self._venv_sh, - 'pkgname': pkgname}) - self._write(''.join(output)) + logger.log("# virtualenv for %(pkgname)s (found in %(workon_home)s)" % {'pkgname': pkgname, 'workon_home': workon_home}) + if os.path.isdir(workon_home): + for d in sorted(os.listdir(workon_home)): + if os.path.isdir(os.path.join(workon_home, d)): + logger.log(d) else: - self._write(template % {'venv_py': self._venv_py, - 'venv_venv': self._venv_venv, - 'workon_home': self._workon_home, - 'venv_sh': self._venv_sh, - 'pkgname': self._pkgname}) + logger.log("# virtualenv for %(pkgname)s (found in %(workon_home)s)" % {'pkgname': self._pkgname, 'workon_home': self._workon_home}) + if os.path.isdir(self._workon_home): + for d in sorted(os.listdir(self._workon_home)): + if os.path.isdir(os.path.join(self._workon_home, d)): + logger.log(d) def _write(self, src): - fp = open(PATH_ETC_VENV, 'w') + fp = open(PATH_HOME_ETC_VENV, 'w') fp.write(src) fp.close() diff --git a/pythonbrew/commands/version.py b/pythonbrew/commands/version.py index 2144123..5be8a62 100644 --- a/pythonbrew/commands/version.py +++ b/pythonbrew/commands/version.py @@ -8,6 +8,6 @@ class VersionCommand(Command): summary = "Show version" def run_command(self, options, args): - logger.info(VERSION) + logger.log(VERSION) VersionCommand() diff --git a/pythonbrew/curl.py b/pythonbrew/curl.py index 719639c..00e5790 100644 --- a/pythonbrew/curl.py +++ b/pythonbrew/curl.py @@ -4,26 +4,27 @@ import subprocess from subprocess import Popen, PIPE from pythonbrew.log import logger from pythonbrew.util import to_str +from pythonbrew.exceptions import CurlFetchException class Curl(object): def __init__(self): returncode = subprocess.call("command -v curl > /dev/null", shell=True) if returncode: - logger.info("pythonbrew required curl. curl was not found in your path.") + logger.log("pythonbrew required curl. curl was not found in your path.") sys.exit(1) def read(self, url): p = Popen("curl -skL %s" % url, stdout=PIPE, shell=True) p.wait() if p.returncode: - raise + raise Exception('Failed to read.') return p.stdout.read() def readheader(self, url): p = Popen("curl --head -skL %s" % url, stdout=PIPE, shell=True) p.wait() if p.returncode: - raise + raise Exception('Failed to readheader.') respinfo = {} for line in p.stdout: line = to_str(line.strip()) @@ -39,4 +40,4 @@ class Curl(object): p = Popen("curl -# -kL %s -o %s" % (url, filename), shell=True) p.wait() if p.returncode: - raise + raise CurlFetchException('Failed to fetch.') diff --git a/pythonbrew/define.py b/pythonbrew/define.py index bf4dee5..a8ab362 100644 --- a/pythonbrew/define.py +++ b/pythonbrew/define.py @@ -6,16 +6,17 @@ except: import configparser as ConfigParser # pythonbrew version -VERSION = "0.9" +VERSION = "0.10" +# pythonbrew installer root path +INSTALLER_ROOT = os.path.dirname(os.path.abspath(__file__)) + +# Root # pythonbrew root path ROOT = os.environ.get("PYTHONBREW_ROOT") if not ROOT: ROOT = os.path.join(os.environ["HOME"],".pythonbrew") -# pythonbrew installer root path -INSTALLER_ROOT = os.path.dirname(os.path.abspath(__file__)) - # directories PATH_PYTHONS = os.path.join(ROOT,"pythons") PATH_BUILD = os.path.join(ROOT,"build") @@ -38,10 +39,21 @@ PATH_PATCHES_MACOSX_PYTHON24 = os.path.join(PATH_PATCHES_MACOSX,"python24") # files PATH_BIN_PYTHONBREW = os.path.join(PATH_BIN,'pythonbrew') -PATH_ETC_CURRENT = os.path.join(PATH_ETC,'current') -PATH_ETC_TEMP = os.path.join(PATH_ETC,'temp') PATH_ETC_CONFIG = os.path.join(PATH_ETC,'config.cfg') -PATH_ETC_VENV = os.path.join(PATH_ETC, 'venv.run') + +# Home +# pythonbrew home path +PATH_HOME = os.environ.get('PYTHONBREW_HOME') +if not PATH_HOME: + PATH_HOME = os.path.join(os.environ["HOME"],".pythonbrew") + +# directories +PATH_HOME_ETC = os.path.join(PATH_HOME, 'etc') + +# files +PATH_HOME_ETC_VENV = os.path.join(PATH_HOME_ETC, 'venv.run') +PATH_HOME_ETC_CURRENT = os.path.join(PATH_HOME_ETC,'current') +PATH_HOME_ETC_TEMP = os.path.join(PATH_HOME_ETC,'temp') # read config.cfg config = ConfigParser.SafeConfigParser() @@ -58,6 +70,9 @@ DISTRIBUTE_SETUP_DLSITE = _get_or_default('distribute', 'url') # buildout bootstrap download BOOTSTRAP_DLSITE = _get_or_default('bootstrap', 'url') +# virtualenv download +VIRTUALENV_DLSITE = _get_or_default('virtualenv', 'url') + # pythonbrew download PYTHONBREW_UPDATE_URL_MASTER = _get_or_default('pythonbrew', 'master') PYTHONBREW_UPDATE_URL_DEVELOP = _get_or_default('pythonbrew', 'develop') diff --git a/pythonbrew/etc/bashrc b/pythonbrew/etc/bashrc index 82b73c4..8944e1e 100644 --- a/pythonbrew/etc/bashrc +++ b/pythonbrew/etc/bashrc @@ -1,6 +1,20 @@ -PATH_ROOT="@ROOT@" +# settings +PATH_ROOT="$PYTHONBREW_ROOT" +if [ -z "${PATH_ROOT}" ] ; then + PATH_ROOT="$HOME/.pythonbrew" +fi PATH_ETC="$PATH_ROOT/etc" +PATH_HOME="$PYTHONBREW_HOME" +if [ -z "${PATH_HOME}" ] ; then + PATH_HOME="$HOME/.pythonbrew" +fi +PATH_HOME_ETC="$PATH_HOME/etc" + +# py file +PY_PYTHONBREW="$PATH_ROOT/bin/pythonbrew" + +# functions __pythonbrew_set_default() { PATH_PYTHONBREW="$PATH_ROOT/bin" @@ -14,8 +28,9 @@ __pythonbrew_set_path() __pythonbrew_set_temp_path() { - if [[ -s "$PATH_ETC/temp" ]] ; then - source "$PATH_ETC/temp" + if [[ -s "$PATH_HOME_ETC/temp" ]] ; then + source "$PATH_HOME_ETC/temp" + PATH_PYTHONBREW="$PATH_ROOT/bin:$PATH_PYTHONBREW_TEMP" else __pythonbrew_set_default fi @@ -24,8 +39,9 @@ __pythonbrew_set_temp_path() __pythonbrew_set_current_path() { - if [[ -s "$PATH_ETC/current" ]] ; then - source "$PATH_ETC/current" + if [[ -s "$PATH_HOME_ETC/current" ]] ; then + source "$PATH_HOME_ETC/current" + PATH_PYTHONBREW="$PATH_ROOT/bin:$PATH_PYTHONBREW_CURRENT" else __pythonbrew_set_default fi @@ -39,35 +55,35 @@ __pythonbrew_reload() __pythonbrew_use() { - command pythonbrew "$@" + $pythonbrew "$@" [[ $? == 0 ]] && __pythonbrew_set_temp_path } __pythonbrew_switch() { - command pythonbrew "$@" + $pythonbrew "$@" [[ $? == 0 ]] && __pythonbrew_set_current_path } __pythonbrew_off() { - command pythonbrew "$@" + $pythonbrew "$@" [[ $? == 0 ]] && __pythonbrew_set_current_path } __pythonbrew_update() { - command pythonbrew "$@" + $pythonbrew "$@" [[ $? == 0 ]] && __pythonbrew_reload } __pythonbrew_venv() { - command pythonbrew "$@" + $pythonbrew "$@" if [[ $? == 0 ]] ; then - if [[ -s "$PATH_ETC/venv.run" ]] ; then - source "$PATH_ETC/venv.run" - cat /dev/null > "$PATH_ETC/venv.run" + if [[ -s "$PATH_HOME_ETC/venv.run" ]] ; then + source "$PATH_HOME_ETC/venv.run" + cat /dev/null > "$PATH_HOME_ETC/venv.run" fi fi } @@ -87,7 +103,7 @@ __pythonbrew_find_command() done } -pythonbrew() +__pythonbrew_run() { __pythonbrew_find_command "$@" case $command_name in @@ -96,15 +112,27 @@ pythonbrew() off) __pythonbrew_off "$@" ;; update) __pythonbrew_update "$@" ;; venv) __pythonbrew_venv "$@" ;; - *) command pythonbrew "$@" ;; + *) $pythonbrew "$@" ;; esac builtin hash -r } +pythonbrew() +{ + pythonbrew=$PY_PYTHONBREW + __pythonbrew_run "$@" +} + pybrew() { pythonbrew "$@" } +sudopybrew() +{ + pythonbrew="sudo PYTHONBREW_ROOT=$PATH_ROOT PATH=$PATH_PYTHONBREW:$PATH_WITHOUT_PYTHONBREW $PY_PYTHONBREW" + __pythonbrew_run "$@" +} + # main __pythonbrew_set_current_path diff --git a/pythonbrew/etc/config.cfg b/pythonbrew/etc/config.cfg index 1a16836..3f057a4 100644 --- a/pythonbrew/etc/config.cfg +++ b/pythonbrew/etc/config.cfg @@ -4,6 +4,9 @@ url = http://python-distribute.org/distribute_setup.py [bootstrap] url = http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py +[virtualenv] +url = http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz + [pythonbrew] master = https://github.com/utahta/pythonbrew/tarball/master develop = https://github.com/utahta/pythonbrew/tarball/develop diff --git a/pythonbrew/exceptions.py b/pythonbrew/exceptions.py index fd6cee9..69036f1 100644 --- a/pythonbrew/exceptions.py +++ b/pythonbrew/exceptions.py @@ -11,4 +11,6 @@ class AlreadyInstalledException(Exception): """General exception during installing""" class NotSupportedVersionException(Exception): """General exception during installing""" - \ No newline at end of file + +class CurlFetchException(Exception): + """Exception curl during fetching""" diff --git a/pythonbrew/installer/__init__.py b/pythonbrew/installer/__init__.py index f4362e4..0a22bee 100644 --- a/pythonbrew/installer/__init__.py +++ b/pythonbrew/installer/__init__.py @@ -3,10 +3,10 @@ from pythonbrew.log import logger from pythonbrew.define import INSTALLER_ROOT, ROOT, PATH_ETC def install_pythonbrew(): - PythonbrewInstaller().install(INSTALLER_ROOT) - # pythonbrew is only for bash + PythonbrewInstaller.install(INSTALLER_ROOT) + # for bash shrc = yourshrc = "bashrc" - logger.info(""" + logger.log(""" Well-done! Congratulations! The pythonbrew is installed as: @@ -33,4 +33,30 @@ Enjoy pythonbrew at %(ROOT)s!! """ % {'ROOT':ROOT, 'yourshrc':yourshrc, 'shrc':shrc, 'PATH_ETC':PATH_ETC}) def upgrade_pythonbrew(): - PythonbrewInstaller().install(INSTALLER_ROOT) + PythonbrewInstaller.install(INSTALLER_ROOT) + +def systemwide_pythonbrew(): + PythonbrewInstaller.install(INSTALLER_ROOT) + PythonbrewInstaller.systemwide_install() + logger.log(""" +Well-done! Congratulations! + +The pythonbrew is installed as: + + %(ROOT)s + +After that, exit this shell, start a new one, and install some fresh +pythons: + + pythonbrew install 2.7.2 + pythonbrew install 3.2 + +For further instructions, run: + + pythonbrew help + +The default help messages will popup and tell you what to do! + +Enjoy pythonbrew at %(ROOT)s!! +""" % {'ROOT':ROOT}) + \ No newline at end of file diff --git a/pythonbrew/installer/pythonbrewinstaller.py b/pythonbrew/installer/pythonbrewinstaller.py index 14c23bc..eb44c1e 100644 --- a/pythonbrew/installer/pythonbrewinstaller.py +++ b/pythonbrew/installer/pythonbrewinstaller.py @@ -6,15 +6,17 @@ from pythonbrew.util import makedirs, rm_r from pythonbrew.define import PATH_BUILD, PATH_BIN, PATH_DISTS, PATH_PYTHONS,\ PATH_ETC, PATH_SCRIPTS, PATH_SCRIPTS_PYTHONBREW,\ PATH_SCRIPTS_PYTHONBREW_COMMANDS, PATH_BIN_PYTHONBREW,\ - ROOT, PATH_LOG, PATH_PATCHES, PATH_ETC_CONFIG,\ - PATH_SCRIPTS_PYTHONBREW_INSTALLER, PATH_VENVS + PATH_LOG, PATH_PATCHES, PATH_ETC_CONFIG,\ + PATH_SCRIPTS_PYTHONBREW_INSTALLER, PATH_VENVS, PATH_HOME_ETC, ROOT import stat +import time class PythonbrewInstaller(object): """pythonbrew installer: """ - def install(self, installer_root): + @staticmethod + def install(installer_root): # create directories makedirs(PATH_PYTHONS) makedirs(PATH_BUILD) @@ -23,6 +25,7 @@ class PythonbrewInstaller(object): makedirs(PATH_BIN) makedirs(PATH_LOG) makedirs(PATH_VENVS) + makedirs(PATH_HOME_ETC) # create script directories rm_r(PATH_SCRIPTS) @@ -61,12 +64,46 @@ if __name__ == "__main__": os.chmod(PATH_BIN_PYTHONBREW, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) # create a bashrc for pythonbrew - fp = open(os.path.join(PATH_ETC,'bashrc'), 'w') - for line in open(os.path.join(installer_root,'etc','bashrc')): - line = line.replace('@ROOT@', ROOT) - fp.write(line) - fp.close() + shutil.copy(os.path.join(installer_root,'etc','bashrc'), os.path.join(PATH_ETC,'bashrc')) # copy config.cfg shutil.copy(os.path.join(installer_root,'etc','config.cfg'), PATH_ETC_CONFIG) - + + @staticmethod + def systemwide_install(): + profile = """\ +#begin-pythonbrew +if [ -n "${BASH_VERSION:-}" -o -n "${ZSH_VERSION:-}" ] ; then + export PYTHONBREW_ROOT=%(root)s + source "${PYTHONBREW_ROOT}/etc/bashrc" +fi +#end-pythonbrew +""" % {'root': ROOT} + + if os.path.isdir('/etc/profile.d'): + fp = open('/etc/profile.d/pythonbrew.sh', 'w') + fp.write(profile) + fp.close() + elif os.path.isfile('/etc/profile'): + # create backup + shutil.copy('/etc/profile', '/tmp/profile.pythonbrew.%s' % int(time.time())) + + output = [] + is_copy = True + fp = open('/etc/profile', 'r') + for line in fp: + if line.startswith('#begin-pythonbrew'): + is_copy = False + continue + elif line.startswith('#end-pythonbrew'): + is_copy = True + continue + if is_copy: + output.append(line) + fp.close() + output.append(profile) + + fp = open('/etc/profile', 'w') + fp.write(''.join(output)) + fp.close() + diff --git a/pythonbrew/installer/pythoninstaller.py b/pythonbrew/installer/pythoninstaller.py index 50a6a77..eaaacc6 100644 --- a/pythonbrew/installer/pythoninstaller.py +++ b/pythonbrew/installer/pythoninstaller.py @@ -38,7 +38,7 @@ class PythonInstaller(object): pkg = Package(name, options.alias) self.download_url = get_python_version_url(pkg.version) if not self.download_url: - logger.info("Unknown python version: `%s`" % pkg.name) + logger.error("Unknown python version: `%s`" % pkg.name) raise UnknownVersionException filename = Link(self.download_url).filename self.pkg = pkg @@ -83,11 +83,11 @@ class PythonInstaller(object): except: rm_r(self.install_dir) logger.error("Failed to install %s. See %s to see why." % (self.pkg.name, self.logfile)) - logger.info(" pythonbrew install --force %s" % self.pkg.version) + logger.log(" pythonbrew install --force %s" % self.pkg.version) sys.exit(1) self.symlink() self.install_setuptools() - logger.info("Installed %(pkgname)s successfully. Run the following command to switch to %(pkgname)s." + logger.info("\nInstalled %(pkgname)s successfully. Run the following command to switch to %(pkgname)s." % {"pkgname":self.pkg.name}) logger.info(" pythonbrew switch %s" % self.pkg.alias) @@ -107,7 +107,7 @@ class PythonInstaller(object): dl.download(base_url, self.download_url, self.download_file) except: unlink(self.download_file) - logger.info("\nInterrupt to abort. `%s`" % (self.download_url)) + logger.error("Failed to download.\n%s" % (sys.exc_info()[1])) sys.exit(1) # extracting if not extract_downloadfile(self.content_type, self.download_file, self.build_dir): @@ -154,7 +154,7 @@ class PythonInstaller(object): else: s.shell("patch -p0 < %s" % patch) except: - logger.error("Failed to patch `%s`" % self.build_dir) + logger.error("Failed to patch `%s`.\n%s" % (self.build_dir, sys.exc_info()[1])) sys.exit(1) def _add_patches_to_list(self, patch_dir, patch_files): @@ -206,7 +206,7 @@ class PythonInstaller(object): options = self.options pkgname = self.pkg.name if options.no_setuptools: - logger.info("Skip installation of setuptools.") + logger.log("Skip installation of setuptools.") return download_url = DISTRIBUTE_SETUP_DLSITE filename = Link(download_url).filename @@ -228,7 +228,7 @@ class PythonInstaller(object): s.check_call([easy_install, 'pip']) except: logger.error("Failed to install setuptools. See %s/build.log to see why." % (ROOT)) - logger.info("Skip installation of setuptools.") + logger.log("Skip installation of setuptools.") class PythonInstallerMacOSX(PythonInstaller): """Python installer for MacOSX @@ -239,7 +239,7 @@ class PythonInstallerMacOSX(PythonInstaller): # 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) + logger.error("`%s` is not supported on MacOSX Snow Leopard" % self.pkg.name) raise NotSupportedVersionException # set configure options target = get_macosx_deployment_target() diff --git a/pythonbrew/log.py b/pythonbrew/log.py index 3ddf3cd..8b55939 100644 --- a/pythonbrew/log.py +++ b/pythonbrew/log.py @@ -1,43 +1,43 @@ import sys -import logging -class LoggerInfo(object): - def log(self, level, msg, *arg, **keys): - sys.stdout.write("%s\n" % msg) - -class LoggerError(object): - def log(self, level, msg, *arg, **keys): - sys.stderr.write("ERROR: %s\n" % msg) - -class Logger(object): +class Color(object): + DEBUG = '\033[35m' + INFO = '\033[32m' + ERROR = '\033[31m' + ENDC = '\033[0m' - DEBUG = logging.DEBUG - INFO = logging.INFO - ERROR = logging.ERROR + @classmethod + def _deco(cls, msg, color): + return '%s%s%s' % (color, msg, cls.ENDC) - def __init__(self): - self._consumers = [] - consumer = LoggerInfo() - self.add_consumer(Logger.INFO, consumer) + @classmethod + def debug(cls, msg): + return cls._deco(msg, cls.DEBUG) + @classmethod + def info(cls, msg): + return cls._deco(msg, cls.INFO) + @classmethod + def error(cls, msg): + return cls._deco(msg, cls.ERROR) + +class Logger(object): + def debug(self, msg): + self._stdout(Color.debug("DEBUG: %s\n" % msg)) + + def log(self, msg): + self._stdout("%s\n" % (msg)) + + def info(self, msg): + self._stdout(Color.info('%s\n' % msg)) - consumer = LoggerError() - self.add_consumer(Logger.ERROR, consumer) - - def debug(self, msg, *args, **keys): - self._log(Logger.DEBUG, msg, *args, **keys) - - def info(self, msg, *args, **keys): - self._log(Logger.INFO, msg, *args, **keys) + def error(self, msg): + self._stderr(Color.error("ERROR: %s\n" % msg)) - def error(self, msg, *args, **keys): - self._log(Logger.ERROR, msg, *args, **keys) - - def _log(self, level, msg, *args, **keys): - for (consumer_level, consumer) in self._consumers: - if level == consumer_level: - consumer.log(level, msg, *args, **keys) - - def add_consumer(self, level, consumer): - self._consumers.append((level, consumer)) + def _stdout(self, msg): + sys.stdout.write(msg) + sys.stdout.flush() + def _stderr(self, msg): + sys.stderr.write(msg) + sys.stderr.flush() logger = Logger() diff --git a/pythonbrew/util.py b/pythonbrew/util.py index a29ae85..61b42f1 100644 --- a/pythonbrew/util.py +++ b/pythonbrew/util.py @@ -10,7 +10,7 @@ import urllib import subprocess import shlex import select -from pythonbrew.define import PATH_BIN, PATH_ETC_CURRENT, PATH_PYTHONS +from pythonbrew.define import PATH_BIN, PATH_HOME_ETC_CURRENT, PATH_PYTHONS from pythonbrew.exceptions import ShellCommandException from pythonbrew.log import logger @@ -209,10 +209,13 @@ def extract_downloadfile(content_type, download_file, target_dir): return False return True -def get_using_python_path(): - p = subprocess.Popen('command -v python', stdout=subprocess.PIPE, shell=True) +def get_command_path(command): + p = subprocess.Popen('command -v %s' % command, stdout=subprocess.PIPE, shell=True) return to_str(p.communicate()[0].strip()) +def get_using_python_path(): + return get_command_path('python') + def get_using_python_pkgname(): """return: Python- or None""" path = get_using_python_path() @@ -233,8 +236,8 @@ def is_installed(name): return True def set_current_path(path): - fp = open(PATH_ETC_CURRENT, 'w') - fp.write('PATH_PYTHONBREW="%s"\n' % (path)) + fp = open(PATH_HOME_ETC_CURRENT, 'w') + fp.write('PATH_PYTHONBREW_CURRENT="%s"\n' % (path)) fp.close() def path_to_fileurl(path): @@ -268,6 +271,11 @@ def is_str(val): return isinstance(val, str) return False +def is_sequence(val): + if is_str(val): + return False + return (hasattr(val, "__getitem__") or hasattr(val, "__iter__")) + def bltin_any(iter): try: return any(iter) @@ -290,7 +298,9 @@ class Subprocess(object): def shell(self, cmd): if self._debug: - logger.info(cmd) + logger.log(cmd) + if is_sequence(cmd): + cmd = ''.join(cmd) if self._log: if self._verbose: cmd = "(%s) 2>&1 | tee '%s'" % (cmd, self._log) @@ -304,7 +314,7 @@ class Subprocess(object): if is_str(cmd): cmd = shlex.split(cmd) if self._debug: - logger.info(cmd) + logger.log(cmd) fp = ((self._log and open(self._log, 'a')) or None) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self._cwd) @@ -314,7 +324,7 @@ class Subprocess(object): if not line: break if self._verbose: - logger.info(line.strip()) + logger.log(line.strip()) if fp: fp.write(line) fp.flush() diff --git a/pythonbrew_install.py b/pythonbrew_install.py index 0f78ffd..13075c2 100644 --- a/pythonbrew_install.py +++ b/pythonbrew_install.py @@ -1,4 +1,4 @@ -from pythonbrew.installer import install_pythonbrew, upgrade_pythonbrew +from pythonbrew.installer import install_pythonbrew, upgrade_pythonbrew, systemwide_pythonbrew from optparse import OptionParser if __name__ == "__main__": parser = OptionParser() @@ -9,8 +9,17 @@ if __name__ == "__main__": default=False, help="Upgrade." ) + parser.add_option( + '--systemwide', + dest="systemwide", + action="store_true", + default=False, + help="systemwide install." + ) (opt, arg) = parser.parse_args() - if opt.upgrade: + if opt.systemwide: + systemwide_pythonbrew() + elif opt.upgrade: upgrade_pythonbrew() else: install_pythonbrew() diff --git a/stable-version.txt b/stable-version.txt index d893d08..688abaa 100644 --- a/stable-version.txt +++ b/stable-version.txt @@ -1 +1 @@ -0.9 \ No newline at end of file +0.10 \ No newline at end of file diff --git a/tests/test_10_venv.py b/tests/test_10_venv.py index eb5f352..639ca11 100644 --- a/tests/test_10_venv.py +++ b/tests/test_10_venv.py @@ -1,11 +1,21 @@ class VenvOptions(object): python = '2.6.6' all = False + no_site_packages = False def test_venv(): + import os from pythonbrew.commands.venv import VenvCommand + from pythonbrew.util import Subprocess + from pythonbrew.define import PATH_HOME_ETC_VENV + s = Subprocess() c = VenvCommand() + c.run_command(VenvOptions(), ['init']) c.run_command(VenvOptions(), ['create', 'aaa']) + s.shell('source %s' % PATH_HOME_ETC_VENV) c.run_command(VenvOptions(), ['list']) c.run_command(VenvOptions(), ['use', 'aaa']) c.run_command(VenvOptions(), ['delete', 'aaa']) + s.shell('source %s' % PATH_HOME_ETC_VENV) + # finish + os.unlink(PATH_HOME_ETC_VENV)