From b4a6674fba437d706abf15c53235a6a1a8ee550c Mon Sep 17 00:00:00 2001 From: utahta Date: Thu, 21 Jul 2011 02:14:41 +0900 Subject: [PATCH] Added venv command --- ChangeLog | 2 +- PKG-INFO | 27 +++++- README.rst | 10 +++ pythonbrew/commands/buildout.py | 4 +- pythonbrew/commands/list.py | 10 +-- pythonbrew/commands/uninstall.py | 4 +- pythonbrew/commands/venv.py | 93 ++++++++++----------- pythonbrew/define.py | 2 + pythonbrew/etc/bashrc | 37 ++++++++ pythonbrew/installer/pythonbrewinstaller.py | 3 +- pythonbrew/util.py | 9 +- 11 files changed, 133 insertions(+), 68 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6e3837..dcc3575 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,7 @@ - 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. + - `pythonbrew clean` has been removed. Added `pythonbrew cleanup` instead. * 0.7.3 - Improved symlink command diff --git a/PKG-INFO b/PKG-INFO index 6ade579..a074e0c 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -51,7 +51,7 @@ Use the specified python in current shell:: 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 -v test.py # Show verbose output pythonbrew py -p 2.7.2 -p 3.2 test.py # Use the specified pythons List the installed pythons:: @@ -88,6 +88,18 @@ Create/Remove a symbolic link to python (in a directory on your $PATH):: pythonbrew symlink pip # Create a symbolic link to the specified script in bin directory pythonbrew symlink -r # Remove a symbolic link +Runs the buildout with specified or current using python:: + + pythonbrew buildout + pythonbrew buildout -p 2.6.6 + +Create isolated python environments:: + + pythonbrew venv create proj1 + pythonbrew venv list + pythonbrew venv use proj1 + pythonbrew venv delete proj1 + Show version:: pythonbrew version @@ -125,11 +137,20 @@ update off Disable pythonbrew. - + +symlink + Create/Remove a symbolic link to python (in a directory on your $PATH) + +buildout + Runs the buildout with specified or current using python. + +venv + Create isolated python environments. + version Show version. -See more details below:: +See more details below: pythonbrew help diff --git a/README.rst b/README.rst index faf463c..a074e0c 100644 --- a/README.rst +++ b/README.rst @@ -93,6 +93,13 @@ Runs the buildout with specified or current using python:: pythonbrew buildout pythonbrew buildout -p 2.6.6 +Create isolated python environments:: + + pythonbrew venv create proj1 + pythonbrew venv list + pythonbrew venv use proj1 + pythonbrew venv delete proj1 + Show version:: pythonbrew version @@ -137,6 +144,9 @@ symlink buildout Runs the buildout with specified or current using python. +venv + Create isolated python environments. + version Show version. diff --git a/pythonbrew/commands/buildout.py b/pythonbrew/commands/buildout.py index 94cdfdd..81ef50a 100644 --- a/pythonbrew/commands/buildout.py +++ b/pythonbrew/commands/buildout.py @@ -3,7 +3,7 @@ import sys import subprocess from pythonbrew.basecommand import Command from pythonbrew.define import PATH_PYTHONS, BOOTSTRAP_DLSITE, PATH_DISTS -from pythonbrew.util import Package, get_current_use_pkgname, Link, is_installed +from pythonbrew.util import Package, get_using_python_pkgname, Link, is_installed from pythonbrew.log import logger from pythonbrew.downloader import Downloader @@ -26,7 +26,7 @@ class BuildoutCommand(Command): if options.python: pkgname = Package(options.python).name else: - pkgname = get_current_use_pkgname() + pkgname = get_using_python_pkgname() if not is_installed(pkgname): logger.info('%s is not installed.' % pkgname) sys.exit(1) diff --git a/pythonbrew/commands/list.py b/pythonbrew/commands/list.py index f0e3ccc..d9fb902 100644 --- a/pythonbrew/commands/list.py +++ b/pythonbrew/commands/list.py @@ -3,7 +3,8 @@ 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_current_use_pkgname +from pythonbrew.util import Package, get_using_python_pkgname,\ + get_using_python_path from pythonbrew.log import logger class ListCommand(Command): @@ -36,15 +37,14 @@ class ListCommand(Command): def installed(self, options, args): logger.info('# installed pythons') - cur = get_current_use_pkgname() + cur = get_using_python_pkgname() for d in sorted(os.listdir(PATH_PYTHONS)): if cur and cur == d: logger.info('%s (*)' % d) - cur = None else: logger.info('%s' % d) - if cur: - logger.info('%s (*)' % cur) + if not cur: + logger.info('%s (*)' % get_using_python_path()) def available_install(self, options, args): logger.info('# available install pythons') diff --git a/pythonbrew/commands/uninstall.py b/pythonbrew/commands/uninstall.py index 2659bec..0a79e8c 100644 --- a/pythonbrew/commands/uninstall.py +++ b/pythonbrew/commands/uninstall.py @@ -1,7 +1,7 @@ import os from pythonbrew.basecommand import Command from pythonbrew.define import PATH_PYTHONS, PATH_BIN -from pythonbrew.util import off, rm_r, Package, get_current_use_pkgname, unlink,\ +from pythonbrew.util import off, rm_r, Package, get_using_python_pkgname, unlink,\ is_installed from pythonbrew.log import logger @@ -20,7 +20,7 @@ class UninstallCommand(Command): if not is_installed(pkgname): logger.info("`%s` is not installed." % pkgname) continue - if get_current_use_pkgname() == pkgname: + if get_using_python_pkgname() == pkgname: off() for d in os.listdir(PATH_BIN): # remove symlink diff --git a/pythonbrew/commands/venv.py b/pythonbrew/commands/venv.py index df174b3..9fb0ab7 100644 --- a/pythonbrew/commands/venv.py +++ b/pythonbrew/commands/venv.py @@ -1,11 +1,10 @@ import os import sys -import subprocess from pythonbrew.basecommand import Command -from pythonbrew.define import PATH_PYTHONS, BOOTSTRAP_DLSITE, PATH_DISTS -from pythonbrew.util import Package, get_current_use_pkgname, Link +from pythonbrew.define import PATH_PYTHONS, PATH_VENVS, PATH_ETC_VENV +from pythonbrew.util import get_using_python_pkgname, Subprocess, Package,\ + is_installed from pythonbrew.log import logger -from pythonbrew.downloader import Downloader class VenvCommand(Command): name = "venv" @@ -24,61 +23,53 @@ class VenvCommand(Command): def run_command(self, options, args): if not args: - logger.error('Unrecognized command line argument: argument not found.') - sys.exit(1) + logger.error('Unrecognized command line argument: ( see: \'pythonbrew help venv\' )') + sys.exit(1) cmd = args[0] if not cmd in ('create', 'use', 'delete', 'list'): - logger.error('%s command not found.' % cmd) + logger.error('Unrecognized command line argument: ( see: \'pythonbrew help venv\' )') sys.exit(1) - # Decide which version of python to use. if options.python: pkgname = Package(options.python).name else: - pkgname = get_current_use_pkgname() - logger.info('Using %s' % pkgname) + pkgname = get_using_python_pkgname() + if not is_installed(pkgname): + logger.error("%s is not installed." % pkgname) + sys.exit(1) + pkg_dir = os.path.join(PATH_PYTHONS, pkgname) + pkg_bin_dir = os.path.join(pkg_dir, 'bin') - if cmd == 'create': - self._create(args[1:]) - elif cmd == 'use': - self._use(args[1]) - elif cmd == 'delete': - self._delete(args[1:]) + self._pkg_bin_dir = pkg_bin_dir + self._venv_dir = os.path.join(PATH_VENVS, pkgname) + + # check python package name + if not pkgname: + logger.error('Can not create virtual environment before using a python. Try \'pythonbrew switch \'.') + sys.exit(1) + + # has virtualenv & virtualenvwrapper? + if(not os.path.exists(os.path.join(pkg_bin_dir, 'virtualenvwrapper.sh')) or + not os.path.exists(os.path.join(pkg_bin_dir, 'virtualenv'))): + logger.info('Installing virtualenv into %s' % pkg_dir) + s = Subprocess(verbose=True) + s.shell('%s %s %s' % (os.path.join(pkg_bin_dir,'pip'), 'install', 'virtualenvwrapper')) + + # Initialize virtualenv + self._init() + + # check + if cmd == 'use': + if len(args) < 2: + logger.error("Unrecognized command line argument: ( 'pythonbrew venv use ' )") + sys.exit(1) elif cmd == 'list': - self._list() - - # Download bootstrap.py -# download_url = BOOTSTRAP_DLSITE -# filename = Link(download_url).filename -# bootstrap = os.path.join(PATH_DISTS, filename) -# try: -# d = Downloader() -# d.download(filename, download_url, bootstrap) -# except: -# logger.error("Failed to download. `%s`" % download_url) -# sys.exit(1) -# -# # Using bootstrap.py -# if subprocess.call([python, bootstrap, '-d']): -# logger.error('Failed to bootstrap.') -# sys.exit(1) -# -# # Using buildout -# subprocess.call(['./bin/buildout']) - - def _create(self, projects): - """Create python environment""" - for proj in projects: - print proj - - def _use(self, project): - print project - - def _delete(self, projects): - for proj in projects: - print proj - - def _list(self): - print 'list' + logger.info('# virtualenv for %s (found in %s)' % (pkgname, self._venv_dir)) + + def _init(self): + fp = open(PATH_ETC_VENV, 'w') + fp.write("VIRTUALENVWRAPPER_PYTHON=%s\n" % os.path.join(self._pkg_bin_dir, 'python')) + fp.write("WORKON_HOME=%s" % self._venv_dir) + fp.close() VenvCommand() diff --git a/pythonbrew/define.py b/pythonbrew/define.py index 761d829..5258694 100644 --- a/pythonbrew/define.py +++ b/pythonbrew/define.py @@ -23,6 +23,7 @@ PATH_DISTS = os.path.join(ROOT,"dists") PATH_ETC = os.path.join(ROOT,"etc") PATH_BIN = os.path.join(ROOT,"bin") PATH_LOG = os.path.join(ROOT,"log") +PATH_VENVS = os.path.join(ROOT, "venvs") PATH_SCRIPTS = os.path.join(ROOT,"scripts") PATH_SCRIPTS_PYTHONBREW = os.path.join(PATH_SCRIPTS,"pythonbrew") PATH_SCRIPTS_PYTHONBREW_COMMANDS = os.path.join(PATH_SCRIPTS_PYTHONBREW,"commands") @@ -40,6 +41,7 @@ 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') # read config.cfg config = ConfigParser.SafeConfigParser() diff --git a/pythonbrew/etc/bashrc b/pythonbrew/etc/bashrc index 6639033..8963f66 100644 --- a/pythonbrew/etc/bashrc +++ b/pythonbrew/etc/bashrc @@ -61,6 +61,42 @@ __pythonbrew_update() [[ $? == 0 ]] && __pythonbrew_reload } +__pythonbrew_venv() +{ + command pythonbrew "$@" + if [[ $? == 0 ]] ; then + source "$PATH_ETC/venv" + args=() + for arg in "$@" ; do + if [[ $param_skip = 1 ]] ; then + param_skip=0 + continue + fi + case $arg in + -p) param_skip=1 ; continue ;; + --python) param_skip=1 ; continue ;; + esac + args=("${args[@]}" $arg) + done + for arg in ${args[@]} ; do + case $arg in + create) + for proj in ${args[@]:2} ; do + mkvirtualenv $proj + done + ;; + delete) + for proj in ${args[@]:2} ; do + rmvirtualenv $proj + done + ;; + use) workon ${args[2]} ;; + list) workon ;; + esac + done + fi +} + __pythonbrew_find_command() { command_name="" @@ -84,6 +120,7 @@ pythonbrew() switch) __pythonbrew_switch "$@" ;; off) __pythonbrew_off "$@" ;; update) __pythonbrew_update "$@" ;; + venv) __pythonbrew_venv "$@" ;; *) command pythonbrew "$@" ;; esac builtin hash -r diff --git a/pythonbrew/installer/pythonbrewinstaller.py b/pythonbrew/installer/pythonbrewinstaller.py index bc17bc3..14c23bc 100644 --- a/pythonbrew/installer/pythonbrewinstaller.py +++ b/pythonbrew/installer/pythonbrewinstaller.py @@ -7,7 +7,7 @@ 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_SCRIPTS_PYTHONBREW_INSTALLER, PATH_VENVS import stat class PythonbrewInstaller(object): @@ -22,6 +22,7 @@ class PythonbrewInstaller(object): makedirs(PATH_ETC) makedirs(PATH_BIN) makedirs(PATH_LOG) + makedirs(PATH_VENVS) # create script directories rm_r(PATH_SCRIPTS) diff --git a/pythonbrew/util.py b/pythonbrew/util.py index ab6b661..9bba392 100644 --- a/pythonbrew/util.py +++ b/pythonbrew/util.py @@ -209,10 +209,13 @@ def extract_downloadfile(content_type, download_file, target_dir): return False return True -def get_current_use_pkgname(): - """return: Python- or None""" +def get_using_python_path(): p = subprocess.Popen('command -v python', stdout=subprocess.PIPE, shell=True) - path = to_str(p.communicate()[0].strip()) + return to_str(p.communicate()[0].strip()) + +def get_using_python_pkgname(): + """return: Python- or None""" + path = get_using_python_path() for d in sorted(os.listdir(PATH_PYTHONS)): if path and os.path.samefile(path, os.path.join(PATH_PYTHONS, d, 'bin','python')): return d