mirror of
https://github.com/kennethreitz/heroku-buildpack-python.git
synced 2026-06-05 23:10:16 +00:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5645a433dc | |||
| 715ab8b96a | |||
| b7f1157693 | |||
| ae7b6fc715 | |||
| e0c3b72950 | |||
| 566f7f4555 | |||
| 4ff62b2b41 | |||
| d47970fd81 | |||
| 69bdca063f | |||
| 63cea99415 | |||
| 5ecd27e3b8 | |||
| 206a2dbc04 | |||
| 2a083791b6 | |||
| d5b2b0b464 | |||
| 2eab1ad845 | |||
| 2b16420d41 | |||
| 9fa0889499 | |||
| 99b17fabeb | |||
| 933d3014d7 | |||
| 018e0f31de | |||
| cf1647e937 | |||
| b9f154bf38 | |||
| 4cc18ce0af | |||
| f5ea1c24a3 | |||
| 952b0bb735 | |||
| 8b7edad8a2 | |||
| 02787ac910 | |||
| bcc3ba09ca | |||
| 31e65dc58b | |||
| 9a227e6c73 | |||
| ddc9c24d34 | |||
| 42488a2be7 | |||
| 839486c25b | |||
| 5d56200179 | |||
| fef1d4f7c0 | |||
| 43defcc17e | |||
| f78460e2a7 | |||
| 3448923b69 | |||
| 58a13bc268 | |||
| c18038f986 | |||
| d4356a1f4c | |||
| 3c8f478b65 | |||
| 23493302e6 | |||
| 35ceaf728d | |||
| 5c9412fc33 | |||
| 825c9329eb | |||
| 9ebb990716 | |||
| f964209589 | |||
| 2e699d392e | |||
| 431ecee509 | |||
| 90696215ae | |||
| 5b55261700 | |||
| 727ff90acf | |||
| 0060fdacd8 | |||
| 85ad1fa988 | |||
| 56c022ca41 | |||
| f68e0989ea | |||
| 7381117bb8 | |||
| c9209ebb3d | |||
| 35345d11f5 | |||
| 6ee17b4c26 | |||
| 86267f93a1 | |||
| 50642e7069 | |||
| 8349f291d2 | |||
| 1aad21382e | |||
| 686ee087a5 | |||
| f137ba213a | |||
| 5ae51010cc | |||
| 29d8e7f670 | |||
| 5be3e0ce52 | |||
| ddde30a12e | |||
| 2db5578998 | |||
| 290250836f |
@@ -1,21 +0,0 @@
|
||||
tests:
|
||||
./bin/test
|
||||
|
||||
docs:
|
||||
mkdir -p site
|
||||
shocco -t 'Python Buildpack Compiler' ./bin/compile > site/index.html
|
||||
shocco -t 'Django Buildpack Compiler' ./bin/steps/django > site/django.html
|
||||
shocco -t 'Python Buildpack Detector' ./bin/detect > site/detect.html
|
||||
shocco -t 'Pylibmc Buildpack Compiler' ./bin/steps/pylibmc > site/pylibmc.html
|
||||
shocco -t 'Python Buildpack Changelog' ./Changelog.md > site/changelog.html
|
||||
|
||||
site: docs
|
||||
cd site && git add -A && git commit -m 'update' && git push heroku master
|
||||
|
||||
pip:
|
||||
git clone git@github.com:kennethreitz/pip.git --branch heroku --depth 1
|
||||
rm -fr vendor/virtualenv-1.8.4/virtualenv_support/pip-1.2.1.tar.gz
|
||||
rm -fr pip/.git
|
||||
tar -pczf vendor/virtualenv-1.8.4/virtualenv_support/pip-1.2.1.tar.gz pip
|
||||
rm -fr pip
|
||||
|
||||
@@ -19,11 +19,11 @@ Example usage:
|
||||
...
|
||||
-----> Fetching custom git buildpack... done
|
||||
-----> Python app detected
|
||||
-----> No runtime.txt provided; assuming python-2.7.3.
|
||||
-----> Preparing Python runtime (python-2.7.3)
|
||||
-----> Installing Distribute (0.6.34)
|
||||
-----> Installing Pip (1.2.1)
|
||||
-----> Installing dependencies using Pip (1.2.1)
|
||||
-----> No runtime.txt provided; assuming python-2.7.6.
|
||||
-----> Preparing Python runtime (python-2.7.6)
|
||||
-----> Installing Setuptools (2.1)
|
||||
-----> Installing Pip (1.5.2)
|
||||
-----> Installing dependencies using Pip (1.5.2)
|
||||
Downloading/unpacking Flask==0.7.2 (from -r requirements.txt (line 1))
|
||||
Downloading/unpacking Werkzeug>=0.6.1 (from Flask==0.7.2->-r requirements.txt (line 1))
|
||||
Downloading/unpacking Jinja2>=2.4 (from Flask==0.7.2->-r requirements.txt (line 1))
|
||||
@@ -35,9 +35,9 @@ You can also add it to upcoming builds of an existing application:
|
||||
|
||||
$ heroku config:add BUILDPACK_URL=git://github.com/heroku/heroku-buildpack-python.git
|
||||
|
||||
The buildpack will detect your app as Python if it has the file `requirements.txt` in the root.
|
||||
The buildpack will detect your app as Python if it has the file `requirements.txt` in the root.
|
||||
|
||||
It will use Pip to install your dependencies, vendoring a copy of the Python runtime into your slug.
|
||||
It will use Pip to install your dependencies, vendoring a copy of the Python runtime into your slug.
|
||||
|
||||
Specify a Runtime
|
||||
-----------------
|
||||
@@ -45,10 +45,12 @@ Specify a Runtime
|
||||
You can also provide arbitrary releases Python with a `runtime.txt` file.
|
||||
|
||||
$ cat runtime.txt
|
||||
python-3.3.0
|
||||
|
||||
python-3.3.3
|
||||
|
||||
Runtime options include:
|
||||
|
||||
- python-2.7.3
|
||||
- python-3.3.0
|
||||
- python-2.7.6
|
||||
- python-3.3.3
|
||||
- pypy-1.9 (experimental)
|
||||
|
||||
Other [unsupported runtimes](https://github.com/kennethreitz/python-versions/tree/master/formula) are available as well.
|
||||
|
||||
+139
-79
@@ -1,33 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script serves as the
|
||||
# [**Python Buildpack**](https://github.com/heroku/heroku-buildpack-python)
|
||||
# compiler.
|
||||
# Usage:
|
||||
#
|
||||
# A [buildpack](http://devcenter.heroku.com/articles/buildpacks) is an
|
||||
# adapter between a Python application and Heroku's runtime.
|
||||
#
|
||||
# You can intreract with the Heroku API directly with [heroku.py](https://github.com/heroku/heroku.py/).
|
||||
#
|
||||
# See also: [Release history](/changelog.html), [Detection](/detect.html).
|
||||
#
|
||||
# ## Usage
|
||||
# Compiling an app into a slug is simple:
|
||||
#
|
||||
# $ bin/compile <build-dir> <cache-dir>
|
||||
|
||||
|
||||
# ## Assumptions
|
||||
#
|
||||
# This buildpack makes the following assumptions:
|
||||
#
|
||||
# - The desired Python VM is available on the base system.
|
||||
# - Library dependencies are available on the base system.
|
||||
# - Django applications should not require any platform-specific configuration.
|
||||
|
||||
# <hr />
|
||||
|
||||
# ## Context
|
||||
# $ bin/compile <build-dir> <cache-dir> <env-path>
|
||||
|
||||
# Fail fast and fail hard.
|
||||
set -eo pipefail
|
||||
@@ -40,6 +15,8 @@ BIN_DIR=$(cd $(dirname $0); pwd) # absolute path
|
||||
ROOT_DIR=$(dirname $BIN_DIR)
|
||||
BUILD_DIR=$1
|
||||
CACHE_DIR=$2
|
||||
ENV_DIR=$3
|
||||
|
||||
|
||||
CACHED_DIRS=".heroku"
|
||||
|
||||
@@ -48,13 +25,30 @@ VIRTUALENV_LOC=".heroku/venv"
|
||||
LEGACY_TRIGGER="lib/python2.7"
|
||||
PROFILE_PATH="$BUILD_DIR/.profile.d/python.sh"
|
||||
|
||||
# Python version. This will be used in the future to specify custom Pythons.
|
||||
DEFAULT_PYTHON_VERSION="python-2.7.3"
|
||||
DEFAULT_PYTHON_VERSION="python-2.7.6"
|
||||
PYTHON_EXE="/app/.heroku/python/bin/python"
|
||||
PIP_VERSION="1.5.2"
|
||||
SETUPTOOLS_VERSION="2.1"
|
||||
|
||||
# Setup bpwatch
|
||||
export PATH=$PATH:$ROOT_DIR/vendor/bpwatch
|
||||
LOGPLEX_KEY="t.b396af7f-ad75-4643-8b9e-ebb288acc624"
|
||||
export BPWATCH_STORE_PATH=$CACHE_DIR/bpwatch.json
|
||||
BUILDPACK_VERSION=v28
|
||||
|
||||
# Support Anvil Build_IDs
|
||||
[ ! "$REQUEST_ID" ] && REQUEST_ID=$SLUG_ID
|
||||
|
||||
# Sanitizing environment variables.
|
||||
unset GIT_DIR PYTHONHOME PYTHONPATH LD_LIBRARY_PATH LIBRARY_PATH
|
||||
|
||||
bpwatch init $LOGPLEX_KEY
|
||||
bpwatch build python $BUILDPACK_VERSION $REQUEST_ID
|
||||
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
|
||||
|
||||
bpwatch start compile
|
||||
|
||||
|
||||
# We'll need to send these statics to other scripts we `source`.
|
||||
export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH
|
||||
|
||||
@@ -66,28 +60,41 @@ APP_DIR='/app'
|
||||
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
|
||||
|
||||
# Copy Anvil app dir to temporary storage...
|
||||
mkdir -p $TMP_APP_DIR
|
||||
deep-mv $APP_DIR $TMP_APP_DIR
|
||||
bpwatch start anvil_appdir_stage
|
||||
if [ "$SLUG_ID" ]; then
|
||||
mkdir -p $TMP_APP_DIR
|
||||
deep-mv $APP_DIR $TMP_APP_DIR
|
||||
else
|
||||
deep-rm $APP_DIR
|
||||
fi
|
||||
bpwatch stop anvil_appdir_stage
|
||||
|
||||
# Copy Application code in.
|
||||
deep-mv $BUILD_DIR $APP_DIR
|
||||
bpwatch start appdir_stage
|
||||
deep-mv $BUILD_DIR $APP_DIR
|
||||
bpwatch stop appdir_stage
|
||||
|
||||
# Set new context.
|
||||
ORIG_BUILD_DIR=$BUILD_DIR
|
||||
BUILD_DIR=$APP_DIR
|
||||
|
||||
# Prepend proper path buildpack use.
|
||||
export PATH=$BUILD_DIR/.heroku/python/bin:$PATH
|
||||
export PATH=$BUILD_DIR/.heroku/python/bin:$BUILD_DIR/.heroku/vendor/bin:$PATH
|
||||
export PYTHONUNBUFFERED=1
|
||||
|
||||
# ## Build Time
|
||||
#
|
||||
export LANG=en_US.UTF-8
|
||||
export C_INCLUDE_PATH=/app/.heroku/vendor/include:$BUILD_DIR/.heroku/vendor/include
|
||||
export CPLUS_INCLUDE_PATH=/app/.heroku/vendor/include:$BUILD_DIR/.heroku/vendor/include
|
||||
export LIBRARY_PATH=/app/.heroku/vendor/lib:$BUILD_DIR/.heroku/vendor/lib
|
||||
export LD_LIBRARY_PATH=/app/.heroku/vendor/lib:$BUILD_DIR/.heroku/vendor/lib
|
||||
export PKG_CONFIG_PATH=/app/.heroku/vendor/lib/pkg-config:$BUILD_DIR/.heroku/vendor/lib/pkg-config
|
||||
|
||||
# Switch to the repo's context.
|
||||
cd $BUILD_DIR
|
||||
|
||||
# Experimental pre_compile hook.
|
||||
source $BIN_DIR/steps/hooks/pre_compile
|
||||
bpwatch start pre_compile
|
||||
source $BIN_DIR/steps/hooks/pre_compile
|
||||
bpwatch stop pre_compile
|
||||
|
||||
# If no requirements given, assume `setup.py develop`.
|
||||
if [ ! -f requirements.txt ]; then
|
||||
@@ -95,6 +102,11 @@ if [ ! -f requirements.txt ]; then
|
||||
echo "-e ." > requirements.txt
|
||||
fi
|
||||
|
||||
# Sticky runtimes.
|
||||
if [ -f $CACHE_DIR/.heroku/python-version ]; then
|
||||
DEFAULT_PYTHON_VERSION=$(cat $CACHE_DIR/.heroku/python-version)
|
||||
fi
|
||||
|
||||
# If no runtime given, assume default version.
|
||||
if [ ! -f runtime.txt ]; then
|
||||
puts-step "No runtime.txt provided; assuming $DEFAULT_PYTHON_VERSION."
|
||||
@@ -105,13 +117,17 @@ fi
|
||||
mkdir -p $CACHE_DIR
|
||||
|
||||
# Purge "old-style" virtualenvs.
|
||||
[ -d $CACHE_DIR/$LEGACY_TRIGGER ] && rm -fr $CACHE_DIR/.heroku/bin $CACHE_DIR/.heroku/lib $CACHE_DIR/.heroku/include
|
||||
[ -d $CACHE_DIR/$VIRTUALENV_LOC ] && rm -fr $CACHE_DIR/.heroku/venv $CACHE_DIR/.heroku/src
|
||||
bpwatch start clear_old_venvs
|
||||
[ -d $CACHE_DIR/$LEGACY_TRIGGER ] && rm -fr $CACHE_DIR/.heroku/bin $CACHE_DIR/.heroku/lib $CACHE_DIR/.heroku/include
|
||||
[ -d $CACHE_DIR/$VIRTUALENV_LOC ] && rm -fr $CACHE_DIR/.heroku/venv $CACHE_DIR/.heroku/src
|
||||
bpwatch stop clear_old_venvs
|
||||
|
||||
# Restore old artifacts from the cache.
|
||||
for dir in $CACHED_DIRS; do
|
||||
cp -R $CACHE_DIR/$dir . &> /dev/null || true
|
||||
done
|
||||
bpwatch start restore_cache
|
||||
for dir in $CACHED_DIRS; do
|
||||
cp -R $CACHE_DIR/$dir . &> /dev/null || true
|
||||
done
|
||||
bpwatch stop restore_cache
|
||||
|
||||
set +e
|
||||
# Create set-aside `.heroku` folder.
|
||||
@@ -126,8 +142,10 @@ PYTHON_VERSION=$(cat runtime.txt)
|
||||
# Install Python.
|
||||
if [ -f .heroku/python-version ]; then
|
||||
if [ ! $(cat .heroku/python-version) = $PYTHON_VERSION ]; then
|
||||
puts-step "Found $(cat .heroku/python-version), removing."
|
||||
rm -fr .heroku/python
|
||||
bpwatch start uninstall_python
|
||||
puts-step "Found $(cat .heroku/python-version), removing."
|
||||
rm -fr .heroku/python
|
||||
bpwatch stop uninstall_python
|
||||
else
|
||||
SKIP_INSTALL=1
|
||||
fi
|
||||
@@ -135,77 +153,119 @@ fi
|
||||
|
||||
|
||||
if [ ! "$SKIP_INSTALL" ]; then
|
||||
puts-step "Preparing Python runtime ($PYTHON_VERSION)"
|
||||
curl http://envy-versions.s3.amazonaws.com/$PYTHON_VERSION.tar.bz2 -s | tar jx &> /dev/null
|
||||
if [[ $? != 0 ]] ; then
|
||||
puts-warn "Requested runtime ($PYTHON_VERSION) was not found."
|
||||
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
||||
exit 1
|
||||
fi
|
||||
mv python .heroku/python
|
||||
bpwatch start install_python
|
||||
puts-step "Preparing Python runtime ($PYTHON_VERSION)"
|
||||
curl http://envy-versions.s3.amazonaws.com/$PYTHON_VERSION.tar.bz2 -s | tar jx &> /dev/null
|
||||
if [[ $? != 0 ]] ; then
|
||||
puts-warn "Requested runtime ($PYTHON_VERSION) was not found."
|
||||
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
||||
exit 1
|
||||
fi
|
||||
mv python .heroku/python
|
||||
bpwatch stop install_python
|
||||
|
||||
# Record for future reference.
|
||||
echo $PYTHON_VERSION > .heroku/python-version
|
||||
WORKING_DIR=$(pwd)
|
||||
|
||||
# Prepare it for the real world
|
||||
puts-step "Installing Distribute (0.6.34)"
|
||||
cd $ROOT_DIR/vendor/distribute-0.6.34/
|
||||
python setup.py install &> /dev/null
|
||||
cd $WORKING_DIR
|
||||
|
||||
puts-step "Installing Pip (1.2.1)"
|
||||
cd $ROOT_DIR/vendor/pip-1.2.1/
|
||||
python setup.py install &> /dev/null
|
||||
cd $WORKING_DIR
|
||||
FRESH_PYTHON=true
|
||||
|
||||
hash -r
|
||||
else
|
||||
puts-step "Using Python runtime ($PYTHON_VERSION)"
|
||||
fi
|
||||
|
||||
# If Pip isn't up to date:
|
||||
if [ "$FRESH_PYTHON" ] || [[ ! $(pip --version) == *$PIP_VERSION* ]]; then
|
||||
WORKING_DIR=$(pwd)
|
||||
|
||||
bpwatch start prepare_environment
|
||||
|
||||
bpwatch start install_setuptools
|
||||
# Prepare it for the real world
|
||||
puts-step "Installing Setuptools ($SETUPTOOLS_VERSION)"
|
||||
cd $ROOT_DIR/vendor/setuptools-$SETUPTOOLS_VERSION/
|
||||
python setup.py install &> /dev/null
|
||||
cd $WORKING_DIR
|
||||
bpwatch stop install_setuptoools
|
||||
|
||||
bpwatch start install_pip
|
||||
puts-step "Installing Pip ($PIP_VERSION)"
|
||||
cd $ROOT_DIR/vendor/pip-$PIP_VERSION/
|
||||
python setup.py install &> /dev/null
|
||||
cd $WORKING_DIR
|
||||
|
||||
bpwatch stop install_pip
|
||||
bpwatch stop prepare_environment
|
||||
fi
|
||||
|
||||
set -e
|
||||
hash -r
|
||||
|
||||
# Pylibmc support.
|
||||
# See [`bin/steps/pylibmc`](pylibmc.html).
|
||||
source $BIN_DIR/steps/pylibmc
|
||||
bpwatch start pylibmc_install
|
||||
source $BIN_DIR/steps/pylibmc
|
||||
bpwatch stop pylibmc_install
|
||||
|
||||
# Install Mercurial if it appears to be required.
|
||||
if (grep -Fiq "hg+" requirements.txt) then
|
||||
pip install --use-mirrors mercurial | cleanup | indent
|
||||
bpwatch start mercurial_install
|
||||
/app/.heroku/python/bin/pip install mercurial | cleanup | indent
|
||||
bpwatch stop mercurial_install
|
||||
fi
|
||||
|
||||
# Install dependencies with Pip.
|
||||
puts-step "Installing dependencies using Pip (1.2.1)"
|
||||
pip install --use-mirrors -r requirements.txt --exists-action=w --src=./.heroku/src | cleanup | indent
|
||||
puts-step "Installing dependencies using Pip ($PIP_VERSION)"
|
||||
|
||||
|
||||
[ ! "$FRESH_PYTHON" ] && bpwatch start pip_install
|
||||
[ "$FRESH_PYTHON" ] && bpwatch start pip_install_first
|
||||
|
||||
/app/.heroku/python/bin/pip install -r requirements.txt --exists-action=w --src=./.heroku/src | cleanup | indent
|
||||
|
||||
[ ! "$FRESH_PYTHON" ] && bpwatch stop pip_install
|
||||
[ "$FRESH_PYTHON" ] && bpwatch stop pip_install_first
|
||||
|
||||
# Django collectstatic support.
|
||||
source $BIN_DIR/steps/collectstatic
|
||||
bpwatch start collectstatic
|
||||
sub-env $BIN_DIR/steps/collectstatic
|
||||
bpwatch stop collectstatic
|
||||
|
||||
# ### Finalize
|
||||
#
|
||||
|
||||
# Store new artifacts in cache.
|
||||
for dir in $CACHED_DIRS; do
|
||||
rm -rf $CACHE_DIR/$dir
|
||||
cp -R $dir $CACHE_DIR/
|
||||
done
|
||||
|
||||
# Set context environment variables.
|
||||
set-env PATH '$HOME/.heroku/python/bin:$PATH'
|
||||
set-env PYTHONUNBUFFERED true
|
||||
set-env PYTHONHOME /app/.heroku/python
|
||||
set-default-env LIBRARY_PATH /app/.heroku/vendor/lib
|
||||
set-default-env LD_LIBRARY_PATH /app/.heroku/vendor/lib
|
||||
set-default-env LANG en_US.UTF-8
|
||||
set-default-env PYTHONHASHSEED random
|
||||
set-default-env PYTHONPATH /app/
|
||||
un-set-env PYTHONHOME
|
||||
|
||||
|
||||
# Experimental post_compile hook.
|
||||
source $BIN_DIR/steps/hooks/post_compile
|
||||
bpwatch start post_compile
|
||||
source $BIN_DIR/steps/hooks/post_compile
|
||||
bpwatch stop post_compile
|
||||
|
||||
# Store new artifacts in cache.
|
||||
bpwatch start dump_cache
|
||||
for dir in $CACHED_DIRS; do
|
||||
rm -rf $CACHE_DIR/$dir
|
||||
cp -R $dir $CACHE_DIR/
|
||||
done
|
||||
bpwatch stop dump_cache
|
||||
|
||||
# ### Fin.
|
||||
bpwatch start appdir_commit
|
||||
deep-mv $BUILD_DIR $ORIG_BUILD_DIR
|
||||
bpwatch stop appdir_commit
|
||||
|
||||
deep-mv $BUILD_DIR $ORIG_BUILD_DIR
|
||||
deep-mv $TMP_APP_DIR $APP_DIR
|
||||
bpwatch start anvil_appdir_commit
|
||||
if [ "$SLUG_ID" ]; then
|
||||
deep-mv $TMP_APP_DIR $APP_DIR
|
||||
fi
|
||||
|
||||
bpwatch stop anvil_appdir_commit
|
||||
bpwatch stop compile
|
||||
|
||||
+2
-2
@@ -18,6 +18,6 @@ if [[ $MANAGE_FILE ]]; then
|
||||
cat <<EOF
|
||||
|
||||
addons:
|
||||
shared-database:5mb
|
||||
heroku-postgresql:hobby-dev
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
Regular → Executable
+3
-5
@@ -7,13 +7,11 @@ indent() {
|
||||
}
|
||||
|
||||
MANAGE_FILE=$(find . -maxdepth 3 -type f -name 'manage.py' | head -1)
|
||||
MANAGE_FILE=${MANAGE_FILE:2}
|
||||
MANAGE_FILE=${MANAGE_FILE:-fakepath}
|
||||
|
||||
if [ -f .heroku/collectstatic_disabled ]; then
|
||||
DISABLE_COLLECTSTATIC=1
|
||||
fi
|
||||
[ -f .heroku/collectstatic_disabled ] && DISABLE_COLLECTSTATIC=1
|
||||
|
||||
if [ ! "$DISABLE_COLLECTSTATIC" ]; then
|
||||
if [ ! "$DISABLE_COLLECTSTATIC" ] && [ -f "$MANAGE_FILE" ]; then
|
||||
set +e
|
||||
|
||||
# Check if collectstatic is configured properly.
|
||||
|
||||
Regular → Executable
+1
-1
@@ -3,5 +3,5 @@
|
||||
if [ -f bin/post_compile ]; then
|
||||
echo "-----> Running post-compile hook"
|
||||
chmod +x bin/post_compile
|
||||
bin/post_compile
|
||||
sub-env bin/post_compile
|
||||
fi
|
||||
Regular → Executable
+1
-1
@@ -3,5 +3,5 @@
|
||||
if [ -f bin/pre_compile ]; then
|
||||
echo "-----> Running pre-compile hook"
|
||||
chmod +x bin/pre_compile
|
||||
bin/pre_compile
|
||||
sub-env bin/pre_compile
|
||||
fi
|
||||
+1
-1
@@ -16,7 +16,7 @@ VENDORED_MEMCACHED="http://cl.ly/0a191R3K160t1w1P0N25/vendor-libmemcached.tar.gz
|
||||
source $BIN_DIR/utils
|
||||
|
||||
# If pylibmc exists within requirements, use vendored libmemcached.
|
||||
if (grep -Fiq "pylibmc" requirements.txt) then
|
||||
if (grep -Eiq "^\s*pylibmc" requirements.txt) then
|
||||
echo "-----> Noticed pylibmc. Bootstrapping libmemcached."
|
||||
cd .heroku
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#
|
||||
# Create a Heroku app with the following buildpack:
|
||||
# https://github.com/ddollar/buildpack-tet
|
||||
# https://github.com/ddollar/buildpack-test
|
||||
#
|
||||
# Push this Python buildpack to that Heroku app to
|
||||
# run the tests.
|
||||
@@ -20,6 +20,12 @@ testDetectWithEmptyReqs() {
|
||||
assertCapturedSuccess
|
||||
}
|
||||
|
||||
testDetectDjango15() {
|
||||
detect "django-1.5-skeleton"
|
||||
assertCapturedEquals "Python"
|
||||
assertCapturedSuccess
|
||||
}
|
||||
|
||||
testDetectDjango14() {
|
||||
detect "django-1.4-skeleton"
|
||||
assertCapturedEquals "Python"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Script started on Wed Dec 19 22:40:46 2012
|
||||
[1m[7m%[27m[1m[0m
|
||||
|
||||
@@ -52,3 +52,29 @@ function deep-mv (){
|
||||
rm -fr $1/!(tmp)
|
||||
find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
|
||||
}
|
||||
|
||||
# Does some serious deleting.
|
||||
function deep-rm (){
|
||||
rm -fr $1/!(tmp)
|
||||
find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
|
||||
}
|
||||
|
||||
|
||||
sub-env() {
|
||||
|
||||
WHITELIST=${2:-''}
|
||||
BLACKLIST=${3:-'^(GIT_DIR|PYTHONHOME|PYTHONPATH|LD_LIBRARY_PATH|LIBRARY_PATH|PATH)$'}
|
||||
|
||||
(
|
||||
if [ -d "$ENV_DIR" ]; then
|
||||
for e in $(ls $ENV_DIR); do
|
||||
echo "$e" | grep -E "$WHITELIST" | grep -qvE "$BLACKLIST" &&
|
||||
export "$e=$(cat $ENV_DIR/$e)"
|
||||
:
|
||||
done
|
||||
fi
|
||||
|
||||
$1
|
||||
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
# Django settings for haystack project.
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@example.com'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
|
||||
'NAME': '', # Or path to database file if using sqlite3.
|
||||
# The following settings are not used with sqlite3:
|
||||
'USER': '',
|
||||
'PASSWORD': '',
|
||||
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
|
||||
'PORT': '', # Set to empty string for default.
|
||||
}
|
||||
}
|
||||
|
||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
||||
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
# Local time zone for this installation. Choices can be found here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# although not all choices may be available on all operating systems.
|
||||
# In a Windows environment this must be set to your system time zone.
|
||||
TIME_ZONE = 'America/Chicago'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# If you set this to False, Django will not format dates, numbers and
|
||||
# calendars according to the current locale.
|
||||
USE_L10N = True
|
||||
|
||||
# If you set this to False, Django will not use timezone-aware datetimes.
|
||||
USE_TZ = True
|
||||
|
||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
||||
# Example: "/var/www/example.com/media/"
|
||||
MEDIA_ROOT = ''
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://example.com/media/", "http://media.example.com/"
|
||||
MEDIA_URL = ''
|
||||
|
||||
# Absolute path to the directory static files should be collected to.
|
||||
# Don't put anything in this directory yourself; store your static files
|
||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
||||
# Example: "/var/www/example.com/static/"
|
||||
STATIC_ROOT = ''
|
||||
|
||||
# URL prefix for static files.
|
||||
# Example: "http://example.com/static/", "http://static.example.com/"
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Additional locations of static files
|
||||
STATICFILES_DIRS = (
|
||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
# List of finder classes that know how to find static files in
|
||||
# various locations.
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
||||
)
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = '@w-1$9#jh05!qvbh#1k)c4=w9llcq116f$5(4&s_c)n4@%n=pc'
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
# 'django.template.loaders.eggs.Loader',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
# Uncomment the next line for simple clickjacking protection:
|
||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'haystack.urls'
|
||||
|
||||
# Python dotted path to the WSGI application used by Django's runserver.
|
||||
WSGI_APPLICATION = 'haystack.wsgi.application'
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
# Uncomment the next line to enable the admin:
|
||||
# 'django.contrib.admin',
|
||||
# Uncomment the next line to enable admin documentation:
|
||||
# 'django.contrib.admindocs',
|
||||
)
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
from django.conf.urls import patterns, include, url
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
# from django.contrib import admin
|
||||
# admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Examples:
|
||||
# url(r'^$', 'haystack.views.home', name='home'),
|
||||
# url(r'^haystack/', include('haystack.foo.urls')),
|
||||
|
||||
# Uncomment the admin/doc line below to enable admin documentation:
|
||||
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
# url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
WSGI config for haystack project.
|
||||
|
||||
This module contains the WSGI application used by Django's development server
|
||||
and any production WSGI deployments. It should expose a module-level variable
|
||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
||||
this application via the ``WSGI_APPLICATION`` setting.
|
||||
|
||||
Usually you will have the standard Django WSGI application here, but it also
|
||||
might make sense to replace the whole Django WSGI application with a custom one
|
||||
that later delegates to the Django one. For example, you could introduce WSGI
|
||||
middleware here, or combine a Django application with an application of another
|
||||
framework.
|
||||
|
||||
"""
|
||||
import os
|
||||
|
||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "haystack.settings"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "haystack.settings")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
||||
|
||||
# Apply WSGI middleware here.
|
||||
# from helloworld.wsgi import HelloWorldApplication
|
||||
# application = HelloWorldApplication(application)
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "haystack.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
@@ -0,0 +1 @@
|
||||
django==1.5
|
||||
@@ -0,0 +1,2 @@
|
||||
pylibmc
|
||||
psycopg2
|
||||
@@ -1 +1,2 @@
|
||||
httpbin
|
||||
requests
|
||||
distribute==0.6.49
|
||||
@@ -1 +1 @@
|
||||
python-2.7.3
|
||||
python-3.3.2
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
DEFAULT_PATH = '{0}.zip'.format(os.path.abspath(__file__))
|
||||
BPWATCH_DISTRO_PATH = os.environ.get('BPWATCH_DISTRO_PATH', DEFAULT_PATH)
|
||||
|
||||
sys.path.insert(0, BPWATCH_DISTRO_PATH)
|
||||
|
||||
import bp_cli
|
||||
bp_cli.main()
|
||||
Vendored
BIN
Binary file not shown.
Vendored
-487
@@ -1,487 +0,0 @@
|
||||
=======
|
||||
CHANGES
|
||||
=======
|
||||
|
||||
----------
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
+ Issue #341: 0.6.33 fails to build under python 2.4
|
||||
|
||||
------
|
||||
0.6.33
|
||||
------
|
||||
|
||||
* Fix 2 errors with Jython 2.5.
|
||||
* Fix 1 failure with Jython 2.5 and 2.7.
|
||||
* Disable workaround for Jython scripts on Linux systems.
|
||||
* Issue #336: `setup.py` no longer masks failure exit code when tests fail.
|
||||
* Fix issue in pkg_resources where try/except around a platform-dependent
|
||||
import would trigger hook load failures on Mercurial. See pull request 32
|
||||
for details.
|
||||
* Issue #341: Fix a ResourceWarning.
|
||||
|
||||
------
|
||||
0.6.32
|
||||
------
|
||||
|
||||
* Fix test suite with Python 2.6.
|
||||
* Fix some DeprecationWarnings and ResourceWarnings.
|
||||
* Issue #335: Backed out `setup_requires` superceding installed requirements
|
||||
until regression can be addressed.
|
||||
|
||||
------
|
||||
0.6.31
|
||||
------
|
||||
|
||||
* Issue #303: Make sure the manifest only ever contains UTF-8 in Python 3.
|
||||
* Issue #329: Properly close files created by tests for compatibility with
|
||||
Jython.
|
||||
* Work around Jython bugs `#1980 <http://bugs.jython.org/issue1980>`_ and
|
||||
`#1981 <http://bugs.jython.org/issue1981>`_.
|
||||
* Issue #334: Provide workaround for packages that reference `sys.__stdout__`
|
||||
such as numpy does. This change should address
|
||||
`virtualenv #359 <https://github.com/pypa/virtualenv/issues/359>`_ as long
|
||||
as the system encoding is UTF-8 or the IO encoding is specified in the
|
||||
environment, i.e.::
|
||||
|
||||
PYTHONIOENCODING=utf8 pip install numpy
|
||||
|
||||
* Fix for encoding issue when installing from Windows executable on Python 3.
|
||||
* Issue #323: Allow `setup_requires` requirements to supercede installed
|
||||
requirements. Added some new keyword arguments to existing pkg_resources
|
||||
methods. Also had to updated how __path__ is handled for namespace packages
|
||||
to ensure that when a new egg distribution containing a namespace package is
|
||||
placed on sys.path, the entries in __path__ are found in the same order they
|
||||
would have been in had that egg been on the path when pkg_resources was
|
||||
first imported.
|
||||
|
||||
------
|
||||
0.6.30
|
||||
------
|
||||
|
||||
* Issue #328: Clean up temporary directories in distribute_setup.py.
|
||||
* Fix fatal bug in distribute_setup.py.
|
||||
|
||||
------
|
||||
0.6.29
|
||||
------
|
||||
|
||||
* Pull Request #14: Honor file permissions in zip files.
|
||||
* Issue #327: Merged pull request #24 to fix a dependency problem with pip.
|
||||
* Merged pull request #23 to fix https://github.com/pypa/virtualenv/issues/301.
|
||||
* If Sphinx is installed, the `upload_docs` command now runs `build_sphinx`
|
||||
to produce uploadable documentation.
|
||||
* Issue #326: `upload_docs` provided mangled auth credentials under Python 3.
|
||||
* Issue #320: Fix check for "createable" in distribute_setup.py.
|
||||
* Issue #305: Remove a warning that was triggered during normal operations.
|
||||
* Issue #311: Print metadata in UTF-8 independent of platform.
|
||||
* Issue #303: Read manifest file with UTF-8 encoding under Python 3.
|
||||
* Issue #301: Allow to run tests of namespace packages when using 2to3.
|
||||
* Issue #304: Prevent import loop in site.py under Python 3.3.
|
||||
* Issue #283: Reenable scanning of `*.pyc` / `*.pyo` files on Python 3.3.
|
||||
* Issue #299: The develop command didn't work on Python 3, when using 2to3,
|
||||
as the egg link would go to the Python 2 source. Linking to the 2to3'd code
|
||||
in build/lib makes it work, although you will have to rebuild the module
|
||||
before testing it.
|
||||
* Issue #306: Even if 2to3 is used, we build in-place under Python 2.
|
||||
* Issue #307: Prints the full path when .svn/entries is broken.
|
||||
* Issue #313: Support for sdist subcommands (Python 2.7)
|
||||
* Issue #314: test_local_index() would fail an OS X.
|
||||
* Issue #310: Non-ascii characters in a namespace __init__.py causes errors.
|
||||
* Issue #218: Improved documentation on behavior of `package_data` and
|
||||
`include_package_data`. Files indicated by `package_data` are now included
|
||||
in the manifest.
|
||||
* `distribute_setup.py` now allows a `--download-base` argument for retrieving
|
||||
distribute from a specified location.
|
||||
|
||||
------
|
||||
0.6.28
|
||||
------
|
||||
|
||||
* Issue #294: setup.py can now be invoked from any directory.
|
||||
* Scripts are now installed honoring the umask.
|
||||
* Added support for .dist-info directories.
|
||||
* Issue #283: Fix and disable scanning of `*.pyc` / `*.pyo` files on
|
||||
Python 3.3.
|
||||
|
||||
------
|
||||
0.6.27
|
||||
------
|
||||
|
||||
* Support current snapshots of CPython 3.3.
|
||||
* Distribute now recognizes README.rst as a standard, default readme file.
|
||||
* Exclude 'encodings' modules when removing modules from sys.modules.
|
||||
Workaround for #285.
|
||||
* Issue #231: Don't fiddle with system python when used with buildout
|
||||
(bootstrap.py)
|
||||
|
||||
------
|
||||
0.6.26
|
||||
------
|
||||
|
||||
* Issue #183: Symlinked files are now extracted from source distributions.
|
||||
* Issue #227: Easy_install fetch parameters are now passed during the
|
||||
installation of a source distribution; now fulfillment of setup_requires
|
||||
dependencies will honor the parameters passed to easy_install.
|
||||
|
||||
------
|
||||
0.6.25
|
||||
------
|
||||
|
||||
* Issue #258: Workaround a cache issue
|
||||
* Issue #260: distribute_setup.py now accepts the --user parameter for
|
||||
Python 2.6 and later.
|
||||
* Issue #262: package_index.open_with_auth no longer throws LookupError
|
||||
on Python 3.
|
||||
* Issue #269: AttributeError when an exception occurs reading Manifest.in
|
||||
on late releases of Python.
|
||||
* Issue #272: Prevent TypeError when namespace package names are unicode
|
||||
and single-install-externally-managed is used. Also fixes PIP issue
|
||||
449.
|
||||
* Issue #273: Legacy script launchers now install with Python2/3 support.
|
||||
|
||||
------
|
||||
0.6.24
|
||||
------
|
||||
|
||||
* Issue #249: Added options to exclude 2to3 fixers
|
||||
|
||||
------
|
||||
0.6.23
|
||||
------
|
||||
|
||||
* Issue #244: Fixed a test
|
||||
* Issue #243: Fixed a test
|
||||
* Issue #239: Fixed a test
|
||||
* Issue #240: Fixed a test
|
||||
* Issue #241: Fixed a test
|
||||
* Issue #237: Fixed a test
|
||||
* Issue #238: easy_install now uses 64bit executable wrappers on 64bit Python
|
||||
* Issue #208: Fixed parsed_versions, it now honors post-releases as noted in the documentation
|
||||
* Issue #207: Windows cli and gui wrappers pass CTRL-C to child python process
|
||||
* Issue #227: easy_install now passes its arguments to setup.py bdist_egg
|
||||
* Issue #225: Fixed a NameError on Python 2.5, 2.4
|
||||
|
||||
------
|
||||
0.6.21
|
||||
------
|
||||
|
||||
* Issue #225: FIxed a regression on py2.4
|
||||
|
||||
------
|
||||
0.6.20
|
||||
------
|
||||
|
||||
* Issue #135: Include url in warning when processing URLs in package_index.
|
||||
* Issue #212: Fix issue where easy_instal fails on Python 3 on windows installer.
|
||||
* Issue #213: Fix typo in documentation.
|
||||
|
||||
------
|
||||
0.6.19
|
||||
------
|
||||
|
||||
* Issue 206: AttributeError: 'HTTPMessage' object has no attribute 'getheaders'
|
||||
|
||||
------
|
||||
0.6.18
|
||||
------
|
||||
|
||||
* Issue 210: Fixed a regression introduced by Issue 204 fix.
|
||||
|
||||
------
|
||||
0.6.17
|
||||
------
|
||||
|
||||
* Support 'DISTRIBUTE_DISABLE_VERSIONED_EASY_INSTALL_SCRIPT' environment
|
||||
variable to allow to disable installation of easy_install-${version} script.
|
||||
* Support Python >=3.1.4 and >=3.2.1.
|
||||
* Issue 204: Don't try to import the parent of a namespace package in
|
||||
declare_namespace
|
||||
* Issue 196: Tolerate responses with multiple Content-Length headers
|
||||
* Issue 205: Sandboxing doesn't preserve working_set. Leads to setup_requires
|
||||
problems.
|
||||
|
||||
------
|
||||
0.6.16
|
||||
------
|
||||
|
||||
* Builds sdist gztar even on Windows (avoiding Issue 193).
|
||||
* Issue 192: Fixed metadata omitted on Windows when package_dir
|
||||
specified with forward-slash.
|
||||
* Issue 195: Cython build support.
|
||||
* Issue 200: Issues with recognizing 64-bit packages on Windows.
|
||||
|
||||
------
|
||||
0.6.15
|
||||
------
|
||||
|
||||
* Fixed typo in bdist_egg
|
||||
* Several issues under Python 3 has been solved.
|
||||
* Issue 146: Fixed missing DLL files after easy_install of windows exe package.
|
||||
|
||||
------
|
||||
0.6.14
|
||||
------
|
||||
|
||||
* Issue 170: Fixed unittest failure. Thanks to Toshio.
|
||||
* Issue 171: Fixed race condition in unittests cause deadlocks in test suite.
|
||||
* Issue 143: Fixed a lookup issue with easy_install.
|
||||
Thanks to David and Zooko.
|
||||
* Issue 174: Fixed the edit mode when its used with setuptools itself
|
||||
|
||||
------
|
||||
0.6.13
|
||||
------
|
||||
|
||||
* Issue 160: 2.7 gives ValueError("Invalid IPv6 URL")
|
||||
* Issue 150: Fixed using ~/.local even in a --no-site-packages virtualenv
|
||||
* Issue 163: scan index links before external links, and don't use the md5 when
|
||||
comparing two distributions
|
||||
|
||||
------
|
||||
0.6.12
|
||||
------
|
||||
|
||||
* Issue 149: Fixed various failures on 2.3/2.4
|
||||
|
||||
------
|
||||
0.6.11
|
||||
------
|
||||
|
||||
* Found another case of SandboxViolation - fixed
|
||||
* Issue 15 and 48: Introduced a socket timeout of 15 seconds on url openings
|
||||
* Added indexsidebar.html into MANIFEST.in
|
||||
* Issue 108: Fixed TypeError with Python3.1
|
||||
* Issue 121: Fixed --help install command trying to actually install.
|
||||
* Issue 112: Added an os.makedirs so that Tarek's solution will work.
|
||||
* Issue 133: Added --no-find-links to easy_install
|
||||
* Added easy_install --user
|
||||
* Issue 100: Fixed develop --user not taking '.' in PYTHONPATH into account
|
||||
* Issue 134: removed spurious UserWarnings. Patch by VanLindberg
|
||||
* Issue 138: cant_write_to_target error when setup_requires is used.
|
||||
* Issue 147: respect the sys.dont_write_bytecode flag
|
||||
|
||||
------
|
||||
0.6.10
|
||||
------
|
||||
|
||||
* Reverted change made for the DistributionNotFound exception because
|
||||
zc.buildout uses the exception message to get the name of the
|
||||
distribution.
|
||||
|
||||
-----
|
||||
0.6.9
|
||||
-----
|
||||
|
||||
* Issue 90: unknown setuptools version can be added in the working set
|
||||
* Issue 87: setupt.py doesn't try to convert distribute_setup.py anymore
|
||||
Initial Patch by arfrever.
|
||||
* Issue 89: added a side bar with a download link to the doc.
|
||||
* Issue 86: fixed missing sentence in pkg_resources doc.
|
||||
* Added a nicer error message when a DistributionNotFound is raised.
|
||||
* Issue 80: test_develop now works with Python 3.1
|
||||
* Issue 93: upload_docs now works if there is an empty sub-directory.
|
||||
* Issue 70: exec bit on non-exec files
|
||||
* Issue 99: now the standalone easy_install command doesn't uses a
|
||||
"setup.cfg" if any exists in the working directory. It will use it
|
||||
only if triggered by ``install_requires`` from a setup.py call
|
||||
(install, develop, etc).
|
||||
* Issue 101: Allowing ``os.devnull`` in Sandbox
|
||||
* Issue 92: Fixed the "no eggs" found error with MacPort
|
||||
(platform.mac_ver() fails)
|
||||
* Issue 103: test_get_script_header_jython_workaround not run
|
||||
anymore under py3 with C or POSIX local. Contributed by Arfrever.
|
||||
* Issue 104: remvoved the assertion when the installation fails,
|
||||
with a nicer message for the end user.
|
||||
* Issue 100: making sure there's no SandboxViolation when
|
||||
the setup script patches setuptools.
|
||||
|
||||
-----
|
||||
0.6.8
|
||||
-----
|
||||
|
||||
* Added "check_packages" in dist. (added in Setuptools 0.6c11)
|
||||
* Fixed the DONT_PATCH_SETUPTOOLS state.
|
||||
|
||||
-----
|
||||
0.6.7
|
||||
-----
|
||||
|
||||
* Issue 58: Added --user support to the develop command
|
||||
* Issue 11: Generated scripts now wrap their call to the script entry point
|
||||
in the standard "if name == 'main'"
|
||||
* Added the 'DONT_PATCH_SETUPTOOLS' environment variable, so virtualenv
|
||||
can drive an installation that doesn't patch a global setuptools.
|
||||
* Reviewed unladen-swallow specific change from
|
||||
http://code.google.com/p/unladen-swallow/source/detail?spec=svn875&r=719
|
||||
and determined that it no longer applies. Distribute should work fine with
|
||||
Unladen Swallow 2009Q3.
|
||||
* Issue 21: Allow PackageIndex.open_url to gracefully handle all cases of a
|
||||
httplib.HTTPException instead of just InvalidURL and BadStatusLine.
|
||||
* Removed virtual-python.py from this distribution and updated documentation
|
||||
to point to the actively maintained virtualenv instead.
|
||||
* Issue 64: use_setuptools no longer rebuilds the distribute egg every
|
||||
time it is run
|
||||
* use_setuptools now properly respects the requested version
|
||||
* use_setuptools will no longer try to import a distribute egg for the
|
||||
wrong Python version
|
||||
* Issue 74: no_fake should be True by default.
|
||||
* Issue 72: avoid a bootstrapping issue with easy_install -U
|
||||
|
||||
-----
|
||||
0.6.6
|
||||
-----
|
||||
|
||||
* Unified the bootstrap file so it works on both py2.x and py3k without 2to3
|
||||
(patch by Holger Krekel)
|
||||
|
||||
-----
|
||||
0.6.5
|
||||
-----
|
||||
|
||||
* Issue 65: cli.exe and gui.exe are now generated at build time,
|
||||
depending on the platform in use.
|
||||
|
||||
* Issue 67: Fixed doc typo (PEP 381/382)
|
||||
|
||||
* Distribute no longer shadows setuptools if we require a 0.7-series
|
||||
setuptools. And an error is raised when installing a 0.7 setuptools with
|
||||
distribute.
|
||||
|
||||
* When run from within buildout, no attempt is made to modify an existing
|
||||
setuptools egg, whether in a shared egg directory or a system setuptools.
|
||||
|
||||
* Fixed a hole in sandboxing allowing builtin file to write outside of
|
||||
the sandbox.
|
||||
|
||||
-----
|
||||
0.6.4
|
||||
-----
|
||||
|
||||
* Added the generation of `distribute_setup_3k.py` during the release.
|
||||
This closes issue #52.
|
||||
|
||||
* Added an upload_docs command to easily upload project documentation to
|
||||
PyPI's http://packages.python.org. This close issue #56.
|
||||
|
||||
* Fixed a bootstrap bug on the use_setuptools() API.
|
||||
|
||||
-----
|
||||
0.6.3
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Fixed a bunch of calls to file() that caused crashes on Python 3.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed a bug in sorting that caused bootstrap to fail on Python 3.
|
||||
|
||||
-----
|
||||
0.6.2
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Added Python 3 support; see docs/python3.txt.
|
||||
This closes http://bugs.python.org/setuptools/issue39.
|
||||
|
||||
* Added option to run 2to3 automatically when installing on Python 3.
|
||||
This closes issue #31.
|
||||
|
||||
* Fixed invalid usage of requirement.parse, that broke develop -d.
|
||||
This closes http://bugs.python.org/setuptools/issue44.
|
||||
|
||||
* Fixed script launcher for 64-bit Windows.
|
||||
This closes http://bugs.python.org/setuptools/issue2.
|
||||
|
||||
* KeyError when compiling extensions.
|
||||
This closes http://bugs.python.org/setuptools/issue41.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed bootstrap not working on Windows. This closes issue #49.
|
||||
|
||||
* Fixed 2.6 dependencies. This closes issue #50.
|
||||
|
||||
* Make sure setuptools is patched when running through easy_install
|
||||
This closes http://bugs.python.org/setuptools/issue40.
|
||||
|
||||
-----
|
||||
0.6.1
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* package_index.urlopen now catches BadStatusLine and malformed url errors.
|
||||
This closes issue #16 and issue #18.
|
||||
|
||||
* zip_ok is now False by default. This closes
|
||||
http://bugs.python.org/setuptools/issue33.
|
||||
|
||||
* Fixed invalid URL error catching. http://bugs.python.org/setuptools/issue20.
|
||||
|
||||
* Fixed invalid bootstraping with easy_install installation (issue #40).
|
||||
Thanks to Florian Schulze for the help.
|
||||
|
||||
* Removed buildout/bootstrap.py. A new repository will create a specific
|
||||
bootstrap.py script.
|
||||
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* The boostrap process leave setuptools alone if detected in the system
|
||||
and --root or --prefix is provided, but is not in the same location.
|
||||
This closes issue #10.
|
||||
|
||||
---
|
||||
0.6
|
||||
---
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Packages required at build time where not fully present at install time.
|
||||
This closes issue #12.
|
||||
|
||||
* Protected against failures in tarfile extraction. This closes issue #10.
|
||||
|
||||
* Made Jython api_tests.txt doctest compatible. This closes issue #7.
|
||||
|
||||
* sandbox.py replaced builtin type file with builtin function open. This
|
||||
closes issue #6.
|
||||
|
||||
* Immediately close all file handles. This closes issue #3.
|
||||
|
||||
* Added compatibility with Subversion 1.6. This references issue #1.
|
||||
|
||||
pkg_resources
|
||||
=============
|
||||
|
||||
* Avoid a call to /usr/bin/sw_vers on OSX and use the official platform API
|
||||
instead. Based on a patch from ronaldoussoren. This closes issue #5.
|
||||
|
||||
* Fixed a SandboxViolation for mkdir that could occur in certain cases.
|
||||
This closes issue #13.
|
||||
|
||||
* Allow to find_on_path on systems with tight permissions to fail gracefully.
|
||||
This closes issue #9.
|
||||
|
||||
* Corrected inconsistency between documentation and code of add_entry.
|
||||
This closes issue #8.
|
||||
|
||||
* Immediately close all file handles. This closes issue #3.
|
||||
|
||||
easy_install
|
||||
============
|
||||
|
||||
* Immediately close all file handles. This closes issue #3.
|
||||
|
||||
Vendored
-868
@@ -1,868 +0,0 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: distribute
|
||||
Version: 0.6.34
|
||||
Summary: Easily download, build, install, upgrade, and uninstall Python packages
|
||||
Home-page: http://packages.python.org/distribute
|
||||
Author: The fellowship of the packaging
|
||||
Author-email: distutils-sig@python.org
|
||||
License: PSF or ZPL
|
||||
Description: ===============================
|
||||
Installing and Using Distribute
|
||||
===============================
|
||||
|
||||
.. contents:: **Table of Contents**
|
||||
|
||||
-----------
|
||||
Disclaimers
|
||||
-----------
|
||||
|
||||
About the fork
|
||||
==============
|
||||
|
||||
`Distribute` is a fork of the `Setuptools` project.
|
||||
|
||||
Distribute is intended to replace Setuptools as the standard method
|
||||
for working with Python module distributions.
|
||||
|
||||
The fork has two goals:
|
||||
|
||||
- Providing a backward compatible version to replace Setuptools
|
||||
and make all distributions that depend on Setuptools work as
|
||||
before, but with less bugs and behaviorial issues.
|
||||
|
||||
This work is done in the 0.6.x series.
|
||||
|
||||
Starting with version 0.6.2, Distribute supports Python 3.
|
||||
Installing and using distribute for Python 3 code works exactly
|
||||
the same as for Python 2 code, but Distribute also helps you to support
|
||||
Python 2 and Python 3 from the same source code by letting you run 2to3
|
||||
on the code as a part of the build process, by setting the keyword parameter
|
||||
``use_2to3`` to True. See http://packages.python.org/distribute for more
|
||||
information.
|
||||
|
||||
- Refactoring the code, and releasing it in several distributions.
|
||||
This work is being done in the 0.7.x series but not yet released.
|
||||
|
||||
The roadmap is still evolving, and the page that is up-to-date is
|
||||
located at : `http://packages.python.org/distribute/roadmap`.
|
||||
|
||||
If you install `Distribute` and want to switch back for any reason to
|
||||
`Setuptools`, get to the `Uninstallation instructions`_ section.
|
||||
|
||||
More documentation
|
||||
==================
|
||||
|
||||
You can get more information in the Sphinx-based documentation, located
|
||||
at http://packages.python.org/distribute. This documentation includes the old
|
||||
Setuptools documentation that is slowly replaced, and brand new content.
|
||||
|
||||
About the installation process
|
||||
==============================
|
||||
|
||||
The `Distribute` installer modifies your installation by de-activating an
|
||||
existing installation of `Setuptools` in a bootstrap process. This process
|
||||
has been tested in various installation schemes and contexts but in case of a
|
||||
bug during this process your Python installation might be left in a broken
|
||||
state. Since all modified files and directories are copied before the
|
||||
installation starts, you will be able to get back to a normal state by reading
|
||||
the instructions in the `Uninstallation instructions`_ section.
|
||||
|
||||
In any case, it is recommended to save you `site-packages` directory before
|
||||
you start the installation of `Distribute`.
|
||||
|
||||
-------------------------
|
||||
Installation Instructions
|
||||
-------------------------
|
||||
|
||||
Distribute is only released as a source distribution.
|
||||
|
||||
It can be installed using pip, and can be done so with the source tarball,
|
||||
or by using the ``distribute_setup.py`` script provided online.
|
||||
|
||||
``distribute_setup.py`` is the simplest and preferred way on all systems.
|
||||
|
||||
distribute_setup.py
|
||||
===================
|
||||
|
||||
Download
|
||||
`distribute_setup.py <http://python-distribute.org/distribute_setup.py>`_
|
||||
and execute it, using the Python interpreter of your choice.
|
||||
|
||||
If your shell has the ``curl`` program you can do::
|
||||
|
||||
$ curl -O http://python-distribute.org/distribute_setup.py
|
||||
$ python distribute_setup.py
|
||||
|
||||
Notice this file is also provided in the source release.
|
||||
|
||||
pip
|
||||
===
|
||||
|
||||
Run easy_install or pip::
|
||||
|
||||
$ pip install distribute
|
||||
|
||||
Source installation
|
||||
===================
|
||||
|
||||
Download the source tarball, uncompress it, then run the install command::
|
||||
|
||||
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz
|
||||
$ tar -xzvf distribute-0.6.34.tar.gz
|
||||
$ cd distribute-0.6.34
|
||||
$ python setup.py install
|
||||
|
||||
---------------------------
|
||||
Uninstallation Instructions
|
||||
---------------------------
|
||||
|
||||
Like other distutils-based distributions, Distribute doesn't provide an
|
||||
uninstaller yet. It's all done manually! We are all waiting for PEP 376
|
||||
support in Python.
|
||||
|
||||
Distribute is installed in three steps:
|
||||
|
||||
1. it gets out of the way an existing installation of Setuptools
|
||||
2. it installs a `fake` setuptools installation
|
||||
3. it installs distribute
|
||||
|
||||
Distribute can be removed like this:
|
||||
|
||||
- remove the ``distribute*.egg`` file located in your site-packages directory
|
||||
- remove the ``setuptools.pth`` file located in you site-packages directory
|
||||
- remove the easy_install script located in you ``sys.prefix/bin`` directory
|
||||
- remove the ``setuptools*.egg`` directory located in your site-packages directory,
|
||||
if any.
|
||||
|
||||
If you want to get back to setuptools:
|
||||
|
||||
- reinstall setuptools using its instruction.
|
||||
|
||||
Lastly:
|
||||
|
||||
- remove the *.OLD.* directory located in your site-packages directory if any,
|
||||
**once you have checked everything was working correctly again**.
|
||||
|
||||
-------------------------
|
||||
Quick help for developers
|
||||
-------------------------
|
||||
|
||||
To create an egg which is compatible with Distribute, use the same
|
||||
practice as with Setuptools, e.g.::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
)
|
||||
|
||||
To use `pkg_resources` to access data files in the egg, you should
|
||||
require the Setuptools distribution explicitly::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['setuptools']
|
||||
)
|
||||
|
||||
Only if you need Distribute-specific functionality should you depend
|
||||
on it explicitly. In this case, replace the Setuptools dependency::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['distribute']
|
||||
)
|
||||
|
||||
-----------
|
||||
Install FAQ
|
||||
-----------
|
||||
|
||||
- **Why is Distribute wrapping my Setuptools installation?**
|
||||
|
||||
Since Distribute is a fork, and since it provides the same package
|
||||
and modules, it renames the existing Setuptools egg and inserts a
|
||||
new one which merely wraps the Distribute code. This way, full
|
||||
backwards compatibility is kept for packages which rely on the
|
||||
Setuptools modules.
|
||||
|
||||
At the same time, packages can meet their dependency on Setuptools
|
||||
without actually installing it (which would disable Distribute).
|
||||
|
||||
- **How does Distribute interact with virtualenv?**
|
||||
|
||||
Everytime you create a virtualenv it will install setuptools by default.
|
||||
You either need to re-install Distribute in it right after or pass the
|
||||
``--distribute`` option when creating it.
|
||||
|
||||
Once installed, your virtualenv will use Distribute transparently.
|
||||
|
||||
Although, if you have Setuptools installed in your system-wide Python,
|
||||
and if the virtualenv you are in was generated without the `--no-site-packages`
|
||||
option, the Distribute installation will stop.
|
||||
|
||||
You need in this case to build a virtualenv with the `--no-site-packages`
|
||||
option or to install `Distribute` globally.
|
||||
|
||||
- **How does Distribute interacts with zc.buildout?**
|
||||
|
||||
You can use Distribute in your zc.buildout, with the --distribute option,
|
||||
starting at zc.buildout 1.4.2::
|
||||
|
||||
$ python bootstrap.py --distribute
|
||||
|
||||
For previous zc.buildout versions, *the only thing* you need to do
|
||||
is use the bootstrap at `http://python-distribute.org/bootstrap.py`. Run
|
||||
that bootstrap and ``bin/buildout`` (and all other buildout-generated
|
||||
scripts) will transparently use distribute instead of setuptools. You do
|
||||
not need a specific buildout release.
|
||||
|
||||
A shared eggs directory is no problem (since 0.6.6): the setuptools egg is
|
||||
left in place unmodified. So other buildouts that do not yet use the new
|
||||
bootstrap continue to work just fine. And there is no need to list
|
||||
``distribute`` somewhere in your eggs: using the bootstrap is enough.
|
||||
|
||||
The source code for the bootstrap script is located at
|
||||
`http://bitbucket.org/tarek/buildout-distribute`.
|
||||
|
||||
|
||||
|
||||
-----------------------------
|
||||
Feedback and getting involved
|
||||
-----------------------------
|
||||
|
||||
- Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig
|
||||
- Issue tracker: http://bitbucket.org/tarek/distribute/issues/
|
||||
- Code Repository: http://bitbucket.org/tarek/distribute
|
||||
|
||||
=======
|
||||
CHANGES
|
||||
=======
|
||||
|
||||
----------
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
+ `Issue #341`_: 0.6.33 fails to build under python 2.4
|
||||
|
||||
------
|
||||
0.6.33
|
||||
------
|
||||
|
||||
* Fix 2 errors with Jython 2.5.
|
||||
* Fix 1 failure with Jython 2.5 and 2.7.
|
||||
* Disable workaround for Jython scripts on Linux systems.
|
||||
* `Issue #336`_: `setup.py` no longer masks failure exit code when tests fail.
|
||||
* Fix issue in pkg_resources where try/except around a platform-dependent
|
||||
import would trigger hook load failures on Mercurial. See pull request 32
|
||||
for details.
|
||||
* `Issue #341`_: Fix a ResourceWarning.
|
||||
|
||||
------
|
||||
0.6.32
|
||||
------
|
||||
|
||||
* Fix test suite with Python 2.6.
|
||||
* Fix some DeprecationWarnings and ResourceWarnings.
|
||||
* `Issue #335`_: Backed out `setup_requires` superceding installed requirements
|
||||
until regression can be addressed.
|
||||
|
||||
------
|
||||
0.6.31
|
||||
------
|
||||
|
||||
* `Issue #303`_: Make sure the manifest only ever contains UTF-8 in Python 3.
|
||||
* `Issue #329`_: Properly close files created by tests for compatibility with
|
||||
Jython.
|
||||
* Work around Jython bugs `#1980 <http://bugs.jython.org/`issue1980`_>`_ and
|
||||
`#1981 <http://bugs.jython.org/`issue1981`_>`_.
|
||||
* `Issue #334`_: Provide workaround for packages that reference `sys.__stdout__`
|
||||
such as numpy does. This change should address
|
||||
`virtualenv #359 <https://github.com/pypa/virtualenv/issues/359>`_ as long
|
||||
as the system encoding is UTF-8 or the IO encoding is specified in the
|
||||
environment, i.e.::
|
||||
|
||||
PYTHONIOENCODING=utf8 pip install numpy
|
||||
|
||||
* Fix for encoding issue when installing from Windows executable on Python 3.
|
||||
* `Issue #323`_: Allow `setup_requires` requirements to supercede installed
|
||||
requirements. Added some new keyword arguments to existing pkg_resources
|
||||
methods. Also had to updated how __path__ is handled for namespace packages
|
||||
to ensure that when a new egg distribution containing a namespace package is
|
||||
placed on sys.path, the entries in __path__ are found in the same order they
|
||||
would have been in had that egg been on the path when pkg_resources was
|
||||
first imported.
|
||||
|
||||
------
|
||||
0.6.30
|
||||
------
|
||||
|
||||
* `Issue #328`_: Clean up temporary directories in distribute_setup.py.
|
||||
* Fix fatal bug in distribute_setup.py.
|
||||
|
||||
------
|
||||
0.6.29
|
||||
------
|
||||
|
||||
* Pull Request #14: Honor file permissions in zip files.
|
||||
* `Issue #327`_: Merged pull request #24 to fix a dependency problem with pip.
|
||||
* Merged pull request #23 to fix https://github.com/pypa/virtualenv/issues/301.
|
||||
* If Sphinx is installed, the `upload_docs` command now runs `build_sphinx`
|
||||
to produce uploadable documentation.
|
||||
* `Issue #326`_: `upload_docs` provided mangled auth credentials under Python 3.
|
||||
* `Issue #320`_: Fix check for "createable" in distribute_setup.py.
|
||||
* `Issue #305`_: Remove a warning that was triggered during normal operations.
|
||||
* `Issue #311`_: Print metadata in UTF-8 independent of platform.
|
||||
* `Issue #303`_: Read manifest file with UTF-8 encoding under Python 3.
|
||||
* `Issue #301`_: Allow to run tests of namespace packages when using 2to3.
|
||||
* `Issue #304`_: Prevent import loop in site.py under Python 3.3.
|
||||
* `Issue #283`_: Reenable scanning of `*.pyc` / `*.pyo` files on Python 3.3.
|
||||
* `Issue #299`_: The develop command didn't work on Python 3, when using 2to3,
|
||||
as the egg link would go to the Python 2 source. Linking to the 2to3'd code
|
||||
in build/lib makes it work, although you will have to rebuild the module
|
||||
before testing it.
|
||||
* `Issue #306`_: Even if 2to3 is used, we build in-place under Python 2.
|
||||
* `Issue #307`_: Prints the full path when .svn/entries is broken.
|
||||
* `Issue #313`_: Support for sdist subcommands (Python 2.7)
|
||||
* `Issue #314`_: test_local_index() would fail an OS X.
|
||||
* `Issue #310`_: Non-ascii characters in a namespace __init__.py causes errors.
|
||||
* `Issue #218`_: Improved documentation on behavior of `package_data` and
|
||||
`include_package_data`. Files indicated by `package_data` are now included
|
||||
in the manifest.
|
||||
* `distribute_setup.py` now allows a `--download-base` argument for retrieving
|
||||
distribute from a specified location.
|
||||
|
||||
------
|
||||
0.6.28
|
||||
------
|
||||
|
||||
* `Issue #294`_: setup.py can now be invoked from any directory.
|
||||
* Scripts are now installed honoring the umask.
|
||||
* Added support for .dist-info directories.
|
||||
* `Issue #283`_: Fix and disable scanning of `*.pyc` / `*.pyo` files on
|
||||
Python 3.3.
|
||||
|
||||
------
|
||||
0.6.27
|
||||
------
|
||||
|
||||
* Support current snapshots of CPython 3.3.
|
||||
* Distribute now recognizes README.rst as a standard, default readme file.
|
||||
* Exclude 'encodings' modules when removing modules from sys.modules.
|
||||
Workaround for #285.
|
||||
* `Issue #231`_: Don't fiddle with system python when used with buildout
|
||||
(bootstrap.py)
|
||||
|
||||
------
|
||||
0.6.26
|
||||
------
|
||||
|
||||
* `Issue #183`_: Symlinked files are now extracted from source distributions.
|
||||
* `Issue #227`_: Easy_install fetch parameters are now passed during the
|
||||
installation of a source distribution; now fulfillment of setup_requires
|
||||
dependencies will honor the parameters passed to easy_install.
|
||||
|
||||
------
|
||||
0.6.25
|
||||
------
|
||||
|
||||
* `Issue #258`_: Workaround a cache issue
|
||||
* `Issue #260`_: distribute_setup.py now accepts the --user parameter for
|
||||
Python 2.6 and later.
|
||||
* `Issue #262`_: package_index.open_with_auth no longer throws LookupError
|
||||
on Python 3.
|
||||
* `Issue #269`_: AttributeError when an exception occurs reading Manifest.in
|
||||
on late releases of Python.
|
||||
* `Issue #272`_: Prevent TypeError when namespace package names are unicode
|
||||
and single-install-externally-managed is used. Also fixes PIP `issue
|
||||
449`_.
|
||||
* `Issue #273`_: Legacy script launchers now install with Python2/3 support.
|
||||
|
||||
------
|
||||
0.6.24
|
||||
------
|
||||
|
||||
* `Issue #249`_: Added options to exclude 2to3 fixers
|
||||
|
||||
------
|
||||
0.6.23
|
||||
------
|
||||
|
||||
* `Issue #244`_: Fixed a test
|
||||
* `Issue #243`_: Fixed a test
|
||||
* `Issue #239`_: Fixed a test
|
||||
* `Issue #240`_: Fixed a test
|
||||
* `Issue #241`_: Fixed a test
|
||||
* `Issue #237`_: Fixed a test
|
||||
* `Issue #238`_: easy_install now uses 64bit executable wrappers on 64bit Python
|
||||
* `Issue #208`_: Fixed parsed_versions, it now honors post-releases as noted in the documentation
|
||||
* `Issue #207`_: Windows cli and gui wrappers pass CTRL-C to child python process
|
||||
* `Issue #227`_: easy_install now passes its arguments to setup.py bdist_egg
|
||||
* `Issue #225`_: Fixed a NameError on Python 2.5, 2.4
|
||||
|
||||
------
|
||||
0.6.21
|
||||
------
|
||||
|
||||
* `Issue #225`_: FIxed a regression on py2.4
|
||||
|
||||
------
|
||||
0.6.20
|
||||
------
|
||||
|
||||
* `Issue #135`_: Include url in warning when processing URLs in package_index.
|
||||
* `Issue #212`_: Fix issue where easy_instal fails on Python 3 on windows installer.
|
||||
* `Issue #213`_: Fix typo in documentation.
|
||||
|
||||
------
|
||||
0.6.19
|
||||
------
|
||||
|
||||
* `Issue 206`_: AttributeError: 'HTTPMessage' object has no attribute 'getheaders'
|
||||
|
||||
------
|
||||
0.6.18
|
||||
------
|
||||
|
||||
* `Issue 210`_: Fixed a regression introduced by `Issue 204`_ fix.
|
||||
|
||||
------
|
||||
0.6.17
|
||||
------
|
||||
|
||||
* Support 'DISTRIBUTE_DISABLE_VERSIONED_EASY_INSTALL_SCRIPT' environment
|
||||
variable to allow to disable installation of easy_install-${version} script.
|
||||
* Support Python >=3.1.4 and >=3.2.1.
|
||||
* `Issue 204`_: Don't try to import the parent of a namespace package in
|
||||
declare_namespace
|
||||
* `Issue 196`_: Tolerate responses with multiple Content-Length headers
|
||||
* `Issue 205`_: Sandboxing doesn't preserve working_set. Leads to setup_requires
|
||||
problems.
|
||||
|
||||
------
|
||||
0.6.16
|
||||
------
|
||||
|
||||
* Builds sdist gztar even on Windows (avoiding `Issue 193`_).
|
||||
* `Issue 192`_: Fixed metadata omitted on Windows when package_dir
|
||||
specified with forward-slash.
|
||||
* `Issue 195`_: Cython build support.
|
||||
* `Issue 200`_: Issues with recognizing 64-bit packages on Windows.
|
||||
|
||||
------
|
||||
0.6.15
|
||||
------
|
||||
|
||||
* Fixed typo in bdist_egg
|
||||
* Several issues under Python 3 has been solved.
|
||||
* `Issue 146`_: Fixed missing DLL files after easy_install of windows exe package.
|
||||
|
||||
------
|
||||
0.6.14
|
||||
------
|
||||
|
||||
* `Issue 170`_: Fixed unittest failure. Thanks to Toshio.
|
||||
* `Issue 171`_: Fixed race condition in unittests cause deadlocks in test suite.
|
||||
* `Issue 143`_: Fixed a lookup issue with easy_install.
|
||||
Thanks to David and Zooko.
|
||||
* `Issue 174`_: Fixed the edit mode when its used with setuptools itself
|
||||
|
||||
------
|
||||
0.6.13
|
||||
------
|
||||
|
||||
* `Issue 160`_: 2.7 gives ValueError("Invalid IPv6 URL")
|
||||
* `Issue 150`_: Fixed using ~/.local even in a --no-site-packages virtualenv
|
||||
* `Issue 163`_: scan index links before external links, and don't use the md5 when
|
||||
comparing two distributions
|
||||
|
||||
------
|
||||
0.6.12
|
||||
------
|
||||
|
||||
* `Issue 149`_: Fixed various failures on 2.3/2.4
|
||||
|
||||
------
|
||||
0.6.11
|
||||
------
|
||||
|
||||
* Found another case of SandboxViolation - fixed
|
||||
* `Issue 15`_ and 48: Introduced a socket timeout of 15 seconds on url openings
|
||||
* Added indexsidebar.html into MANIFEST.in
|
||||
* `Issue 108`_: Fixed TypeError with Python3.1
|
||||
* `Issue 121`_: Fixed --help install command trying to actually install.
|
||||
* `Issue 112`_: Added an os.makedirs so that Tarek's solution will work.
|
||||
* `Issue 133`_: Added --no-find-links to easy_install
|
||||
* Added easy_install --user
|
||||
* `Issue 100`_: Fixed develop --user not taking '.' in PYTHONPATH into account
|
||||
* `Issue 134`_: removed spurious UserWarnings. Patch by VanLindberg
|
||||
* `Issue 138`_: cant_write_to_target error when setup_requires is used.
|
||||
* `Issue 147`_: respect the sys.dont_write_bytecode flag
|
||||
|
||||
------
|
||||
0.6.10
|
||||
------
|
||||
|
||||
* Reverted change made for the DistributionNotFound exception because
|
||||
zc.buildout uses the exception message to get the name of the
|
||||
distribution.
|
||||
|
||||
-----
|
||||
0.6.9
|
||||
-----
|
||||
|
||||
* `Issue 90`_: unknown setuptools version can be added in the working set
|
||||
* `Issue 87`_: setupt.py doesn't try to convert distribute_setup.py anymore
|
||||
Initial Patch by arfrever.
|
||||
* `Issue 89`_: added a side bar with a download link to the doc.
|
||||
* `Issue 86`_: fixed missing sentence in pkg_resources doc.
|
||||
* Added a nicer error message when a DistributionNotFound is raised.
|
||||
* `Issue 80`_: test_develop now works with Python 3.1
|
||||
* `Issue 93`_: upload_docs now works if there is an empty sub-directory.
|
||||
* `Issue 70`_: exec bit on non-exec files
|
||||
* `Issue 99`_: now the standalone easy_install command doesn't uses a
|
||||
"setup.cfg" if any exists in the working directory. It will use it
|
||||
only if triggered by ``install_requires`` from a setup.py call
|
||||
(install, develop, etc).
|
||||
* `Issue 101`_: Allowing ``os.devnull`` in Sandbox
|
||||
* `Issue 92`_: Fixed the "no eggs" found error with MacPort
|
||||
(platform.mac_ver() fails)
|
||||
* `Issue 103`_: test_get_script_header_jython_workaround not run
|
||||
anymore under py3 with C or POSIX local. Contributed by Arfrever.
|
||||
* `Issue 104`_: remvoved the assertion when the installation fails,
|
||||
with a nicer message for the end user.
|
||||
* `Issue 100`_: making sure there's no SandboxViolation when
|
||||
the setup script patches setuptools.
|
||||
|
||||
-----
|
||||
0.6.8
|
||||
-----
|
||||
|
||||
* Added "check_packages" in dist. (added in Setuptools 0.6c11)
|
||||
* Fixed the DONT_PATCH_SETUPTOOLS state.
|
||||
|
||||
-----
|
||||
0.6.7
|
||||
-----
|
||||
|
||||
* `Issue 58`_: Added --user support to the develop command
|
||||
* `Issue 11`_: Generated scripts now wrap their call to the script entry point
|
||||
in the standard "if name == 'main'"
|
||||
* Added the 'DONT_PATCH_SETUPTOOLS' environment variable, so virtualenv
|
||||
can drive an installation that doesn't patch a global setuptools.
|
||||
* Reviewed unladen-swallow specific change from
|
||||
http://code.google.com/p/unladen-swallow/source/detail?spec=svn875&r=719
|
||||
and determined that it no longer applies. Distribute should work fine with
|
||||
Unladen Swallow 2009Q3.
|
||||
* `Issue 21`_: Allow PackageIndex.open_url to gracefully handle all cases of a
|
||||
httplib.HTTPException instead of just InvalidURL and BadStatusLine.
|
||||
* Removed virtual-python.py from this distribution and updated documentation
|
||||
to point to the actively maintained virtualenv instead.
|
||||
* `Issue 64`_: use_setuptools no longer rebuilds the distribute egg every
|
||||
time it is run
|
||||
* use_setuptools now properly respects the requested version
|
||||
* use_setuptools will no longer try to import a distribute egg for the
|
||||
wrong Python version
|
||||
* `Issue 74`_: no_fake should be True by default.
|
||||
* `Issue 72`_: avoid a bootstrapping issue with easy_install -U
|
||||
|
||||
-----
|
||||
0.6.6
|
||||
-----
|
||||
|
||||
* Unified the bootstrap file so it works on both py2.x and py3k without 2to3
|
||||
(patch by Holger Krekel)
|
||||
|
||||
-----
|
||||
0.6.5
|
||||
-----
|
||||
|
||||
* `Issue 65`_: cli.exe and gui.exe are now generated at build time,
|
||||
depending on the platform in use.
|
||||
|
||||
* `Issue 67`_: Fixed doc typo (PEP 381/382)
|
||||
|
||||
* Distribute no longer shadows setuptools if we require a 0.7-series
|
||||
setuptools. And an error is raised when installing a 0.7 setuptools with
|
||||
distribute.
|
||||
|
||||
* When run from within buildout, no attempt is made to modify an existing
|
||||
setuptools egg, whether in a shared egg directory or a system setuptools.
|
||||
|
||||
* Fixed a hole in sandboxing allowing builtin file to write outside of
|
||||
the sandbox.
|
||||
|
||||
-----
|
||||
0.6.4
|
||||
-----
|
||||
|
||||
* Added the generation of `distribute_setup_3k.py` during the release.
|
||||
This closes `issue #52`_.
|
||||
|
||||
* Added an upload_docs command to easily upload project documentation to
|
||||
PyPI's http://packages.python.org. This close `issue #56`_.
|
||||
|
||||
* Fixed a bootstrap bug on the use_setuptools() API.
|
||||
|
||||
-----
|
||||
0.6.3
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Fixed a bunch of calls to file() that caused crashes on Python 3.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed a bug in sorting that caused bootstrap to fail on Python 3.
|
||||
|
||||
-----
|
||||
0.6.2
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Added Python 3 support; see docs/python3.txt.
|
||||
This closes http://bugs.python.org/setuptools/`issue39`_.
|
||||
|
||||
* Added option to run 2to3 automatically when installing on Python 3.
|
||||
This closes `issue #31`_.
|
||||
|
||||
* Fixed invalid usage of requirement.parse, that broke develop -d.
|
||||
This closes http://bugs.python.org/setuptools/`issue44`_.
|
||||
|
||||
* Fixed script launcher for 64-bit Windows.
|
||||
This closes http://bugs.python.org/setuptools/`issue2`_.
|
||||
|
||||
* KeyError when compiling extensions.
|
||||
This closes http://bugs.python.org/setuptools/`issue41`_.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed bootstrap not working on Windows. This closes `issue #49`_.
|
||||
|
||||
* Fixed 2.6 dependencies. This closes `issue #50`_.
|
||||
|
||||
* Make sure setuptools is patched when running through easy_install
|
||||
This closes http://bugs.python.org/setuptools/`issue40`_.
|
||||
|
||||
-----
|
||||
0.6.1
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* package_index.urlopen now catches BadStatusLine and malformed url errors.
|
||||
This closes `issue #16`_ and `issue #18`_.
|
||||
|
||||
* zip_ok is now False by default. This closes
|
||||
http://bugs.python.org/setuptools/`issue33`_.
|
||||
|
||||
* Fixed invalid URL error catching. http://bugs.python.org/setuptools/`issue20`_.
|
||||
|
||||
* Fixed invalid bootstraping with easy_install installation (`issue #40`_).
|
||||
Thanks to Florian Schulze for the help.
|
||||
|
||||
* Removed buildout/bootstrap.py. A new repository will create a specific
|
||||
bootstrap.py script.
|
||||
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* The boostrap process leave setuptools alone if detected in the system
|
||||
and --root or --prefix is provided, but is not in the same location.
|
||||
This closes `issue #10`_.
|
||||
|
||||
---
|
||||
0.6
|
||||
---
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Packages required at build time where not fully present at install time.
|
||||
This closes `issue #12`_.
|
||||
|
||||
* Protected against failures in tarfile extraction. This closes `issue #10`_.
|
||||
|
||||
* Made Jython api_tests.txt doctest compatible. This closes `issue #7`_.
|
||||
|
||||
* sandbox.py replaced builtin type file with builtin function open. This
|
||||
closes `issue #6`_.
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
* Added compatibility with Subversion 1.6. This references `issue #1`_.
|
||||
|
||||
pkg_resources
|
||||
=============
|
||||
|
||||
* Avoid a call to /usr/bin/sw_vers on OSX and use the official platform API
|
||||
instead. Based on a patch from ronaldoussoren. This closes `issue #5`_.
|
||||
|
||||
* Fixed a SandboxViolation for mkdir that could occur in certain cases.
|
||||
This closes `issue #13`_.
|
||||
|
||||
* Allow to find_on_path on systems with tight permissions to fail gracefully.
|
||||
This closes `issue #9`_.
|
||||
|
||||
* Corrected inconsistency between documentation and code of add_entry.
|
||||
This closes `issue #8`_.
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
easy_install
|
||||
============
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
|
||||
.. _`Issue #135`: http://bitbucket.org/tarek/distribute/issue/135
|
||||
.. _`Issue #183`: http://bitbucket.org/tarek/distribute/issue/183
|
||||
.. _`Issue #207`: http://bitbucket.org/tarek/distribute/issue/207
|
||||
.. _`Issue #208`: http://bitbucket.org/tarek/distribute/issue/208
|
||||
.. _`Issue #212`: http://bitbucket.org/tarek/distribute/issue/212
|
||||
.. _`Issue #213`: http://bitbucket.org/tarek/distribute/issue/213
|
||||
.. _`Issue #218`: http://bitbucket.org/tarek/distribute/issue/218
|
||||
.. _`Issue #225`: http://bitbucket.org/tarek/distribute/issue/225
|
||||
.. _`Issue #227`: http://bitbucket.org/tarek/distribute/issue/227
|
||||
.. _`Issue #231`: http://bitbucket.org/tarek/distribute/issue/231
|
||||
.. _`Issue #237`: http://bitbucket.org/tarek/distribute/issue/237
|
||||
.. _`Issue #238`: http://bitbucket.org/tarek/distribute/issue/238
|
||||
.. _`Issue #239`: http://bitbucket.org/tarek/distribute/issue/239
|
||||
.. _`Issue #240`: http://bitbucket.org/tarek/distribute/issue/240
|
||||
.. _`Issue #241`: http://bitbucket.org/tarek/distribute/issue/241
|
||||
.. _`Issue #243`: http://bitbucket.org/tarek/distribute/issue/243
|
||||
.. _`Issue #244`: http://bitbucket.org/tarek/distribute/issue/244
|
||||
.. _`Issue #249`: http://bitbucket.org/tarek/distribute/issue/249
|
||||
.. _`Issue #258`: http://bitbucket.org/tarek/distribute/issue/258
|
||||
.. _`Issue #260`: http://bitbucket.org/tarek/distribute/issue/260
|
||||
.. _`Issue #262`: http://bitbucket.org/tarek/distribute/issue/262
|
||||
.. _`Issue #269`: http://bitbucket.org/tarek/distribute/issue/269
|
||||
.. _`Issue #272`: http://bitbucket.org/tarek/distribute/issue/272
|
||||
.. _`Issue #273`: http://bitbucket.org/tarek/distribute/issue/273
|
||||
.. _`Issue #283`: http://bitbucket.org/tarek/distribute/issue/283
|
||||
.. _`Issue #294`: http://bitbucket.org/tarek/distribute/issue/294
|
||||
.. _`Issue #299`: http://bitbucket.org/tarek/distribute/issue/299
|
||||
.. _`Issue #301`: http://bitbucket.org/tarek/distribute/issue/301
|
||||
.. _`Issue #303`: http://bitbucket.org/tarek/distribute/issue/303
|
||||
.. _`Issue #304`: http://bitbucket.org/tarek/distribute/issue/304
|
||||
.. _`Issue #305`: http://bitbucket.org/tarek/distribute/issue/305
|
||||
.. _`Issue #306`: http://bitbucket.org/tarek/distribute/issue/306
|
||||
.. _`Issue #307`: http://bitbucket.org/tarek/distribute/issue/307
|
||||
.. _`Issue #310`: http://bitbucket.org/tarek/distribute/issue/310
|
||||
.. _`Issue #311`: http://bitbucket.org/tarek/distribute/issue/311
|
||||
.. _`Issue #313`: http://bitbucket.org/tarek/distribute/issue/313
|
||||
.. _`Issue #314`: http://bitbucket.org/tarek/distribute/issue/314
|
||||
.. _`Issue #320`: http://bitbucket.org/tarek/distribute/issue/320
|
||||
.. _`Issue #323`: http://bitbucket.org/tarek/distribute/issue/323
|
||||
.. _`Issue #326`: http://bitbucket.org/tarek/distribute/issue/326
|
||||
.. _`Issue #327`: http://bitbucket.org/tarek/distribute/issue/327
|
||||
.. _`Issue #328`: http://bitbucket.org/tarek/distribute/issue/328
|
||||
.. _`Issue #329`: http://bitbucket.org/tarek/distribute/issue/329
|
||||
.. _`Issue #334`: http://bitbucket.org/tarek/distribute/issue/334
|
||||
.. _`Issue #335`: http://bitbucket.org/tarek/distribute/issue/335
|
||||
.. _`Issue #336`: http://bitbucket.org/tarek/distribute/issue/336
|
||||
.. _`Issue #341`: http://bitbucket.org/tarek/distribute/issue/341
|
||||
.. _`Issue 100`: http://bitbucket.org/tarek/distribute/issue/100
|
||||
.. _`Issue 101`: http://bitbucket.org/tarek/distribute/issue/101
|
||||
.. _`Issue 103`: http://bitbucket.org/tarek/distribute/issue/103
|
||||
.. _`Issue 104`: http://bitbucket.org/tarek/distribute/issue/104
|
||||
.. _`Issue 108`: http://bitbucket.org/tarek/distribute/issue/108
|
||||
.. _`Issue 11`: http://bitbucket.org/tarek/distribute/issue/11
|
||||
.. _`Issue 112`: http://bitbucket.org/tarek/distribute/issue/112
|
||||
.. _`Issue 121`: http://bitbucket.org/tarek/distribute/issue/121
|
||||
.. _`Issue 133`: http://bitbucket.org/tarek/distribute/issue/133
|
||||
.. _`Issue 134`: http://bitbucket.org/tarek/distribute/issue/134
|
||||
.. _`Issue 138`: http://bitbucket.org/tarek/distribute/issue/138
|
||||
.. _`Issue 143`: http://bitbucket.org/tarek/distribute/issue/143
|
||||
.. _`Issue 146`: http://bitbucket.org/tarek/distribute/issue/146
|
||||
.. _`Issue 147`: http://bitbucket.org/tarek/distribute/issue/147
|
||||
.. _`Issue 149`: http://bitbucket.org/tarek/distribute/issue/149
|
||||
.. _`Issue 15`: http://bitbucket.org/tarek/distribute/issue/15
|
||||
.. _`Issue 150`: http://bitbucket.org/tarek/distribute/issue/150
|
||||
.. _`Issue 160`: http://bitbucket.org/tarek/distribute/issue/160
|
||||
.. _`Issue 163`: http://bitbucket.org/tarek/distribute/issue/163
|
||||
.. _`Issue 170`: http://bitbucket.org/tarek/distribute/issue/170
|
||||
.. _`Issue 171`: http://bitbucket.org/tarek/distribute/issue/171
|
||||
.. _`Issue 174`: http://bitbucket.org/tarek/distribute/issue/174
|
||||
.. _`Issue 192`: http://bitbucket.org/tarek/distribute/issue/192
|
||||
.. _`Issue 193`: http://bitbucket.org/tarek/distribute/issue/193
|
||||
.. _`Issue 195`: http://bitbucket.org/tarek/distribute/issue/195
|
||||
.. _`Issue 196`: http://bitbucket.org/tarek/distribute/issue/196
|
||||
.. _`Issue 200`: http://bitbucket.org/tarek/distribute/issue/200
|
||||
.. _`Issue 204`: http://bitbucket.org/tarek/distribute/issue/204
|
||||
.. _`Issue 205`: http://bitbucket.org/tarek/distribute/issue/205
|
||||
.. _`Issue 206`: http://bitbucket.org/tarek/distribute/issue/206
|
||||
.. _`Issue 21`: http://bitbucket.org/tarek/distribute/issue/21
|
||||
.. _`Issue 210`: http://bitbucket.org/tarek/distribute/issue/210
|
||||
.. _`Issue 58`: http://bitbucket.org/tarek/distribute/issue/58
|
||||
.. _`Issue 64`: http://bitbucket.org/tarek/distribute/issue/64
|
||||
.. _`Issue 65`: http://bitbucket.org/tarek/distribute/issue/65
|
||||
.. _`Issue 67`: http://bitbucket.org/tarek/distribute/issue/67
|
||||
.. _`Issue 70`: http://bitbucket.org/tarek/distribute/issue/70
|
||||
.. _`Issue 72`: http://bitbucket.org/tarek/distribute/issue/72
|
||||
.. _`Issue 74`: http://bitbucket.org/tarek/distribute/issue/74
|
||||
.. _`Issue 80`: http://bitbucket.org/tarek/distribute/issue/80
|
||||
.. _`Issue 86`: http://bitbucket.org/tarek/distribute/issue/86
|
||||
.. _`Issue 87`: http://bitbucket.org/tarek/distribute/issue/87
|
||||
.. _`Issue 89`: http://bitbucket.org/tarek/distribute/issue/89
|
||||
.. _`Issue 90`: http://bitbucket.org/tarek/distribute/issue/90
|
||||
.. _`Issue 92`: http://bitbucket.org/tarek/distribute/issue/92
|
||||
.. _`Issue 93`: http://bitbucket.org/tarek/distribute/issue/93
|
||||
.. _`Issue 99`: http://bitbucket.org/tarek/distribute/issue/99
|
||||
.. _`issue
|
||||
449`: http://bitbucket.org/tarek/distribute/issue/449
|
||||
.. _`issue #1`: http://bitbucket.org/tarek/distribute/issue/1
|
||||
.. _`issue #10`: http://bitbucket.org/tarek/distribute/issue/10
|
||||
.. _`issue #12`: http://bitbucket.org/tarek/distribute/issue/12
|
||||
.. _`issue #13`: http://bitbucket.org/tarek/distribute/issue/13
|
||||
.. _`issue #16`: http://bitbucket.org/tarek/distribute/issue/16
|
||||
.. _`issue #18`: http://bitbucket.org/tarek/distribute/issue/18
|
||||
.. _`issue #3`: http://bitbucket.org/tarek/distribute/issue/3
|
||||
.. _`issue #31`: http://bitbucket.org/tarek/distribute/issue/31
|
||||
.. _`issue #40`: http://bitbucket.org/tarek/distribute/issue/40
|
||||
.. _`issue #49`: http://bitbucket.org/tarek/distribute/issue/49
|
||||
.. _`issue #5`: http://bitbucket.org/tarek/distribute/issue/5
|
||||
.. _`issue #50`: http://bitbucket.org/tarek/distribute/issue/50
|
||||
.. _`issue #52`: http://bitbucket.org/tarek/distribute/issue/52
|
||||
.. _`issue #56`: http://bitbucket.org/tarek/distribute/issue/56
|
||||
.. _`issue #6`: http://bitbucket.org/tarek/distribute/issue/6
|
||||
.. _`issue #7`: http://bitbucket.org/tarek/distribute/issue/7
|
||||
.. _`issue #8`: http://bitbucket.org/tarek/distribute/issue/8
|
||||
.. _`issue #9`: http://bitbucket.org/tarek/distribute/issue/9
|
||||
.. _`issue1980`: http://bitbucket.org/tarek/distribute/issue/1980
|
||||
.. _`issue1981`: http://bitbucket.org/tarek/distribute/issue/1981
|
||||
.. _`issue2`: http://bitbucket.org/tarek/distribute/issue/2
|
||||
.. _`issue20`: http://bitbucket.org/tarek/distribute/issue/20
|
||||
.. _`issue33`: http://bitbucket.org/tarek/distribute/issue/33
|
||||
.. _`issue39`: http://bitbucket.org/tarek/distribute/issue/39
|
||||
.. _`issue40`: http://bitbucket.org/tarek/distribute/issue/40
|
||||
.. _`issue41`: http://bitbucket.org/tarek/distribute/issue/41
|
||||
.. _`issue44`: http://bitbucket.org/tarek/distribute/issue/44
|
||||
|
||||
|
||||
Keywords: CPAN PyPI distutils eggs package management
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Python Software Foundation License
|
||||
Classifier: License :: OSI Approved :: Zope Public License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 2.4
|
||||
Classifier: Programming Language :: Python :: 2.5
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.1
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: System :: Archiving :: Packaging
|
||||
Classifier: Topic :: System :: Systems Administration
|
||||
Classifier: Topic :: Utilities
|
||||
Vendored
-228
@@ -1,228 +0,0 @@
|
||||
===============================
|
||||
Installing and Using Distribute
|
||||
===============================
|
||||
|
||||
.. contents:: **Table of Contents**
|
||||
|
||||
-----------
|
||||
Disclaimers
|
||||
-----------
|
||||
|
||||
About the fork
|
||||
==============
|
||||
|
||||
`Distribute` is a fork of the `Setuptools` project.
|
||||
|
||||
Distribute is intended to replace Setuptools as the standard method
|
||||
for working with Python module distributions.
|
||||
|
||||
The fork has two goals:
|
||||
|
||||
- Providing a backward compatible version to replace Setuptools
|
||||
and make all distributions that depend on Setuptools work as
|
||||
before, but with less bugs and behaviorial issues.
|
||||
|
||||
This work is done in the 0.6.x series.
|
||||
|
||||
Starting with version 0.6.2, Distribute supports Python 3.
|
||||
Installing and using distribute for Python 3 code works exactly
|
||||
the same as for Python 2 code, but Distribute also helps you to support
|
||||
Python 2 and Python 3 from the same source code by letting you run 2to3
|
||||
on the code as a part of the build process, by setting the keyword parameter
|
||||
``use_2to3`` to True. See http://packages.python.org/distribute for more
|
||||
information.
|
||||
|
||||
- Refactoring the code, and releasing it in several distributions.
|
||||
This work is being done in the 0.7.x series but not yet released.
|
||||
|
||||
The roadmap is still evolving, and the page that is up-to-date is
|
||||
located at : `http://packages.python.org/distribute/roadmap`.
|
||||
|
||||
If you install `Distribute` and want to switch back for any reason to
|
||||
`Setuptools`, get to the `Uninstallation instructions`_ section.
|
||||
|
||||
More documentation
|
||||
==================
|
||||
|
||||
You can get more information in the Sphinx-based documentation, located
|
||||
at http://packages.python.org/distribute. This documentation includes the old
|
||||
Setuptools documentation that is slowly replaced, and brand new content.
|
||||
|
||||
About the installation process
|
||||
==============================
|
||||
|
||||
The `Distribute` installer modifies your installation by de-activating an
|
||||
existing installation of `Setuptools` in a bootstrap process. This process
|
||||
has been tested in various installation schemes and contexts but in case of a
|
||||
bug during this process your Python installation might be left in a broken
|
||||
state. Since all modified files and directories are copied before the
|
||||
installation starts, you will be able to get back to a normal state by reading
|
||||
the instructions in the `Uninstallation instructions`_ section.
|
||||
|
||||
In any case, it is recommended to save you `site-packages` directory before
|
||||
you start the installation of `Distribute`.
|
||||
|
||||
-------------------------
|
||||
Installation Instructions
|
||||
-------------------------
|
||||
|
||||
Distribute is only released as a source distribution.
|
||||
|
||||
It can be installed using pip, and can be done so with the source tarball,
|
||||
or by using the ``distribute_setup.py`` script provided online.
|
||||
|
||||
``distribute_setup.py`` is the simplest and preferred way on all systems.
|
||||
|
||||
distribute_setup.py
|
||||
===================
|
||||
|
||||
Download
|
||||
`distribute_setup.py <http://python-distribute.org/distribute_setup.py>`_
|
||||
and execute it, using the Python interpreter of your choice.
|
||||
|
||||
If your shell has the ``curl`` program you can do::
|
||||
|
||||
$ curl -O http://python-distribute.org/distribute_setup.py
|
||||
$ python distribute_setup.py
|
||||
|
||||
Notice this file is also provided in the source release.
|
||||
|
||||
pip
|
||||
===
|
||||
|
||||
Run easy_install or pip::
|
||||
|
||||
$ pip install distribute
|
||||
|
||||
Source installation
|
||||
===================
|
||||
|
||||
Download the source tarball, uncompress it, then run the install command::
|
||||
|
||||
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz
|
||||
$ tar -xzvf distribute-0.6.34.tar.gz
|
||||
$ cd distribute-0.6.34
|
||||
$ python setup.py install
|
||||
|
||||
---------------------------
|
||||
Uninstallation Instructions
|
||||
---------------------------
|
||||
|
||||
Like other distutils-based distributions, Distribute doesn't provide an
|
||||
uninstaller yet. It's all done manually! We are all waiting for PEP 376
|
||||
support in Python.
|
||||
|
||||
Distribute is installed in three steps:
|
||||
|
||||
1. it gets out of the way an existing installation of Setuptools
|
||||
2. it installs a `fake` setuptools installation
|
||||
3. it installs distribute
|
||||
|
||||
Distribute can be removed like this:
|
||||
|
||||
- remove the ``distribute*.egg`` file located in your site-packages directory
|
||||
- remove the ``setuptools.pth`` file located in you site-packages directory
|
||||
- remove the easy_install script located in you ``sys.prefix/bin`` directory
|
||||
- remove the ``setuptools*.egg`` directory located in your site-packages directory,
|
||||
if any.
|
||||
|
||||
If you want to get back to setuptools:
|
||||
|
||||
- reinstall setuptools using its instruction.
|
||||
|
||||
Lastly:
|
||||
|
||||
- remove the *.OLD.* directory located in your site-packages directory if any,
|
||||
**once you have checked everything was working correctly again**.
|
||||
|
||||
-------------------------
|
||||
Quick help for developers
|
||||
-------------------------
|
||||
|
||||
To create an egg which is compatible with Distribute, use the same
|
||||
practice as with Setuptools, e.g.::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
)
|
||||
|
||||
To use `pkg_resources` to access data files in the egg, you should
|
||||
require the Setuptools distribution explicitly::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['setuptools']
|
||||
)
|
||||
|
||||
Only if you need Distribute-specific functionality should you depend
|
||||
on it explicitly. In this case, replace the Setuptools dependency::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['distribute']
|
||||
)
|
||||
|
||||
-----------
|
||||
Install FAQ
|
||||
-----------
|
||||
|
||||
- **Why is Distribute wrapping my Setuptools installation?**
|
||||
|
||||
Since Distribute is a fork, and since it provides the same package
|
||||
and modules, it renames the existing Setuptools egg and inserts a
|
||||
new one which merely wraps the Distribute code. This way, full
|
||||
backwards compatibility is kept for packages which rely on the
|
||||
Setuptools modules.
|
||||
|
||||
At the same time, packages can meet their dependency on Setuptools
|
||||
without actually installing it (which would disable Distribute).
|
||||
|
||||
- **How does Distribute interact with virtualenv?**
|
||||
|
||||
Everytime you create a virtualenv it will install setuptools by default.
|
||||
You either need to re-install Distribute in it right after or pass the
|
||||
``--distribute`` option when creating it.
|
||||
|
||||
Once installed, your virtualenv will use Distribute transparently.
|
||||
|
||||
Although, if you have Setuptools installed in your system-wide Python,
|
||||
and if the virtualenv you are in was generated without the `--no-site-packages`
|
||||
option, the Distribute installation will stop.
|
||||
|
||||
You need in this case to build a virtualenv with the `--no-site-packages`
|
||||
option or to install `Distribute` globally.
|
||||
|
||||
- **How does Distribute interacts with zc.buildout?**
|
||||
|
||||
You can use Distribute in your zc.buildout, with the --distribute option,
|
||||
starting at zc.buildout 1.4.2::
|
||||
|
||||
$ python bootstrap.py --distribute
|
||||
|
||||
For previous zc.buildout versions, *the only thing* you need to do
|
||||
is use the bootstrap at `http://python-distribute.org/bootstrap.py`. Run
|
||||
that bootstrap and ``bin/buildout`` (and all other buildout-generated
|
||||
scripts) will transparently use distribute instead of setuptools. You do
|
||||
not need a specific buildout release.
|
||||
|
||||
A shared eggs directory is no problem (since 0.6.6): the setuptools egg is
|
||||
left in place unmodified. So other buildouts that do not yet use the new
|
||||
bootstrap continue to work just fine. And there is no need to list
|
||||
``distribute`` somewhere in your eggs: using the bootstrap is enough.
|
||||
|
||||
The source code for the bootstrap script is located at
|
||||
`http://bitbucket.org/tarek/buildout-distribute`.
|
||||
|
||||
|
||||
|
||||
-----------------------------
|
||||
Feedback and getting involved
|
||||
-----------------------------
|
||||
|
||||
- Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig
|
||||
- Issue tracker: http://bitbucket.org/tarek/distribute/issues/
|
||||
- Code Repository: http://bitbucket.org/tarek/distribute
|
||||
|
||||
@@ -1,868 +0,0 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: distribute
|
||||
Version: 0.6.34
|
||||
Summary: Easily download, build, install, upgrade, and uninstall Python packages
|
||||
Home-page: http://packages.python.org/distribute
|
||||
Author: The fellowship of the packaging
|
||||
Author-email: distutils-sig@python.org
|
||||
License: PSF or ZPL
|
||||
Description: ===============================
|
||||
Installing and Using Distribute
|
||||
===============================
|
||||
|
||||
.. contents:: **Table of Contents**
|
||||
|
||||
-----------
|
||||
Disclaimers
|
||||
-----------
|
||||
|
||||
About the fork
|
||||
==============
|
||||
|
||||
`Distribute` is a fork of the `Setuptools` project.
|
||||
|
||||
Distribute is intended to replace Setuptools as the standard method
|
||||
for working with Python module distributions.
|
||||
|
||||
The fork has two goals:
|
||||
|
||||
- Providing a backward compatible version to replace Setuptools
|
||||
and make all distributions that depend on Setuptools work as
|
||||
before, but with less bugs and behaviorial issues.
|
||||
|
||||
This work is done in the 0.6.x series.
|
||||
|
||||
Starting with version 0.6.2, Distribute supports Python 3.
|
||||
Installing and using distribute for Python 3 code works exactly
|
||||
the same as for Python 2 code, but Distribute also helps you to support
|
||||
Python 2 and Python 3 from the same source code by letting you run 2to3
|
||||
on the code as a part of the build process, by setting the keyword parameter
|
||||
``use_2to3`` to True. See http://packages.python.org/distribute for more
|
||||
information.
|
||||
|
||||
- Refactoring the code, and releasing it in several distributions.
|
||||
This work is being done in the 0.7.x series but not yet released.
|
||||
|
||||
The roadmap is still evolving, and the page that is up-to-date is
|
||||
located at : `http://packages.python.org/distribute/roadmap`.
|
||||
|
||||
If you install `Distribute` and want to switch back for any reason to
|
||||
`Setuptools`, get to the `Uninstallation instructions`_ section.
|
||||
|
||||
More documentation
|
||||
==================
|
||||
|
||||
You can get more information in the Sphinx-based documentation, located
|
||||
at http://packages.python.org/distribute. This documentation includes the old
|
||||
Setuptools documentation that is slowly replaced, and brand new content.
|
||||
|
||||
About the installation process
|
||||
==============================
|
||||
|
||||
The `Distribute` installer modifies your installation by de-activating an
|
||||
existing installation of `Setuptools` in a bootstrap process. This process
|
||||
has been tested in various installation schemes and contexts but in case of a
|
||||
bug during this process your Python installation might be left in a broken
|
||||
state. Since all modified files and directories are copied before the
|
||||
installation starts, you will be able to get back to a normal state by reading
|
||||
the instructions in the `Uninstallation instructions`_ section.
|
||||
|
||||
In any case, it is recommended to save you `site-packages` directory before
|
||||
you start the installation of `Distribute`.
|
||||
|
||||
-------------------------
|
||||
Installation Instructions
|
||||
-------------------------
|
||||
|
||||
Distribute is only released as a source distribution.
|
||||
|
||||
It can be installed using pip, and can be done so with the source tarball,
|
||||
or by using the ``distribute_setup.py`` script provided online.
|
||||
|
||||
``distribute_setup.py`` is the simplest and preferred way on all systems.
|
||||
|
||||
distribute_setup.py
|
||||
===================
|
||||
|
||||
Download
|
||||
`distribute_setup.py <http://python-distribute.org/distribute_setup.py>`_
|
||||
and execute it, using the Python interpreter of your choice.
|
||||
|
||||
If your shell has the ``curl`` program you can do::
|
||||
|
||||
$ curl -O http://python-distribute.org/distribute_setup.py
|
||||
$ python distribute_setup.py
|
||||
|
||||
Notice this file is also provided in the source release.
|
||||
|
||||
pip
|
||||
===
|
||||
|
||||
Run easy_install or pip::
|
||||
|
||||
$ pip install distribute
|
||||
|
||||
Source installation
|
||||
===================
|
||||
|
||||
Download the source tarball, uncompress it, then run the install command::
|
||||
|
||||
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.34.tar.gz
|
||||
$ tar -xzvf distribute-0.6.34.tar.gz
|
||||
$ cd distribute-0.6.34
|
||||
$ python setup.py install
|
||||
|
||||
---------------------------
|
||||
Uninstallation Instructions
|
||||
---------------------------
|
||||
|
||||
Like other distutils-based distributions, Distribute doesn't provide an
|
||||
uninstaller yet. It's all done manually! We are all waiting for PEP 376
|
||||
support in Python.
|
||||
|
||||
Distribute is installed in three steps:
|
||||
|
||||
1. it gets out of the way an existing installation of Setuptools
|
||||
2. it installs a `fake` setuptools installation
|
||||
3. it installs distribute
|
||||
|
||||
Distribute can be removed like this:
|
||||
|
||||
- remove the ``distribute*.egg`` file located in your site-packages directory
|
||||
- remove the ``setuptools.pth`` file located in you site-packages directory
|
||||
- remove the easy_install script located in you ``sys.prefix/bin`` directory
|
||||
- remove the ``setuptools*.egg`` directory located in your site-packages directory,
|
||||
if any.
|
||||
|
||||
If you want to get back to setuptools:
|
||||
|
||||
- reinstall setuptools using its instruction.
|
||||
|
||||
Lastly:
|
||||
|
||||
- remove the *.OLD.* directory located in your site-packages directory if any,
|
||||
**once you have checked everything was working correctly again**.
|
||||
|
||||
-------------------------
|
||||
Quick help for developers
|
||||
-------------------------
|
||||
|
||||
To create an egg which is compatible with Distribute, use the same
|
||||
practice as with Setuptools, e.g.::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
)
|
||||
|
||||
To use `pkg_resources` to access data files in the egg, you should
|
||||
require the Setuptools distribution explicitly::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['setuptools']
|
||||
)
|
||||
|
||||
Only if you need Distribute-specific functionality should you depend
|
||||
on it explicitly. In this case, replace the Setuptools dependency::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['distribute']
|
||||
)
|
||||
|
||||
-----------
|
||||
Install FAQ
|
||||
-----------
|
||||
|
||||
- **Why is Distribute wrapping my Setuptools installation?**
|
||||
|
||||
Since Distribute is a fork, and since it provides the same package
|
||||
and modules, it renames the existing Setuptools egg and inserts a
|
||||
new one which merely wraps the Distribute code. This way, full
|
||||
backwards compatibility is kept for packages which rely on the
|
||||
Setuptools modules.
|
||||
|
||||
At the same time, packages can meet their dependency on Setuptools
|
||||
without actually installing it (which would disable Distribute).
|
||||
|
||||
- **How does Distribute interact with virtualenv?**
|
||||
|
||||
Everytime you create a virtualenv it will install setuptools by default.
|
||||
You either need to re-install Distribute in it right after or pass the
|
||||
``--distribute`` option when creating it.
|
||||
|
||||
Once installed, your virtualenv will use Distribute transparently.
|
||||
|
||||
Although, if you have Setuptools installed in your system-wide Python,
|
||||
and if the virtualenv you are in was generated without the `--no-site-packages`
|
||||
option, the Distribute installation will stop.
|
||||
|
||||
You need in this case to build a virtualenv with the `--no-site-packages`
|
||||
option or to install `Distribute` globally.
|
||||
|
||||
- **How does Distribute interacts with zc.buildout?**
|
||||
|
||||
You can use Distribute in your zc.buildout, with the --distribute option,
|
||||
starting at zc.buildout 1.4.2::
|
||||
|
||||
$ python bootstrap.py --distribute
|
||||
|
||||
For previous zc.buildout versions, *the only thing* you need to do
|
||||
is use the bootstrap at `http://python-distribute.org/bootstrap.py`. Run
|
||||
that bootstrap and ``bin/buildout`` (and all other buildout-generated
|
||||
scripts) will transparently use distribute instead of setuptools. You do
|
||||
not need a specific buildout release.
|
||||
|
||||
A shared eggs directory is no problem (since 0.6.6): the setuptools egg is
|
||||
left in place unmodified. So other buildouts that do not yet use the new
|
||||
bootstrap continue to work just fine. And there is no need to list
|
||||
``distribute`` somewhere in your eggs: using the bootstrap is enough.
|
||||
|
||||
The source code for the bootstrap script is located at
|
||||
`http://bitbucket.org/tarek/buildout-distribute`.
|
||||
|
||||
|
||||
|
||||
-----------------------------
|
||||
Feedback and getting involved
|
||||
-----------------------------
|
||||
|
||||
- Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig
|
||||
- Issue tracker: http://bitbucket.org/tarek/distribute/issues/
|
||||
- Code Repository: http://bitbucket.org/tarek/distribute
|
||||
|
||||
=======
|
||||
CHANGES
|
||||
=======
|
||||
|
||||
----------
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
+ `Issue #341`_: 0.6.33 fails to build under python 2.4
|
||||
|
||||
------
|
||||
0.6.33
|
||||
------
|
||||
|
||||
* Fix 2 errors with Jython 2.5.
|
||||
* Fix 1 failure with Jython 2.5 and 2.7.
|
||||
* Disable workaround for Jython scripts on Linux systems.
|
||||
* `Issue #336`_: `setup.py` no longer masks failure exit code when tests fail.
|
||||
* Fix issue in pkg_resources where try/except around a platform-dependent
|
||||
import would trigger hook load failures on Mercurial. See pull request 32
|
||||
for details.
|
||||
* `Issue #341`_: Fix a ResourceWarning.
|
||||
|
||||
------
|
||||
0.6.32
|
||||
------
|
||||
|
||||
* Fix test suite with Python 2.6.
|
||||
* Fix some DeprecationWarnings and ResourceWarnings.
|
||||
* `Issue #335`_: Backed out `setup_requires` superceding installed requirements
|
||||
until regression can be addressed.
|
||||
|
||||
------
|
||||
0.6.31
|
||||
------
|
||||
|
||||
* `Issue #303`_: Make sure the manifest only ever contains UTF-8 in Python 3.
|
||||
* `Issue #329`_: Properly close files created by tests for compatibility with
|
||||
Jython.
|
||||
* Work around Jython bugs `#1980 <http://bugs.jython.org/`issue1980`_>`_ and
|
||||
`#1981 <http://bugs.jython.org/`issue1981`_>`_.
|
||||
* `Issue #334`_: Provide workaround for packages that reference `sys.__stdout__`
|
||||
such as numpy does. This change should address
|
||||
`virtualenv #359 <https://github.com/pypa/virtualenv/issues/359>`_ as long
|
||||
as the system encoding is UTF-8 or the IO encoding is specified in the
|
||||
environment, i.e.::
|
||||
|
||||
PYTHONIOENCODING=utf8 pip install numpy
|
||||
|
||||
* Fix for encoding issue when installing from Windows executable on Python 3.
|
||||
* `Issue #323`_: Allow `setup_requires` requirements to supercede installed
|
||||
requirements. Added some new keyword arguments to existing pkg_resources
|
||||
methods. Also had to updated how __path__ is handled for namespace packages
|
||||
to ensure that when a new egg distribution containing a namespace package is
|
||||
placed on sys.path, the entries in __path__ are found in the same order they
|
||||
would have been in had that egg been on the path when pkg_resources was
|
||||
first imported.
|
||||
|
||||
------
|
||||
0.6.30
|
||||
------
|
||||
|
||||
* `Issue #328`_: Clean up temporary directories in distribute_setup.py.
|
||||
* Fix fatal bug in distribute_setup.py.
|
||||
|
||||
------
|
||||
0.6.29
|
||||
------
|
||||
|
||||
* Pull Request #14: Honor file permissions in zip files.
|
||||
* `Issue #327`_: Merged pull request #24 to fix a dependency problem with pip.
|
||||
* Merged pull request #23 to fix https://github.com/pypa/virtualenv/issues/301.
|
||||
* If Sphinx is installed, the `upload_docs` command now runs `build_sphinx`
|
||||
to produce uploadable documentation.
|
||||
* `Issue #326`_: `upload_docs` provided mangled auth credentials under Python 3.
|
||||
* `Issue #320`_: Fix check for "createable" in distribute_setup.py.
|
||||
* `Issue #305`_: Remove a warning that was triggered during normal operations.
|
||||
* `Issue #311`_: Print metadata in UTF-8 independent of platform.
|
||||
* `Issue #303`_: Read manifest file with UTF-8 encoding under Python 3.
|
||||
* `Issue #301`_: Allow to run tests of namespace packages when using 2to3.
|
||||
* `Issue #304`_: Prevent import loop in site.py under Python 3.3.
|
||||
* `Issue #283`_: Reenable scanning of `*.pyc` / `*.pyo` files on Python 3.3.
|
||||
* `Issue #299`_: The develop command didn't work on Python 3, when using 2to3,
|
||||
as the egg link would go to the Python 2 source. Linking to the 2to3'd code
|
||||
in build/lib makes it work, although you will have to rebuild the module
|
||||
before testing it.
|
||||
* `Issue #306`_: Even if 2to3 is used, we build in-place under Python 2.
|
||||
* `Issue #307`_: Prints the full path when .svn/entries is broken.
|
||||
* `Issue #313`_: Support for sdist subcommands (Python 2.7)
|
||||
* `Issue #314`_: test_local_index() would fail an OS X.
|
||||
* `Issue #310`_: Non-ascii characters in a namespace __init__.py causes errors.
|
||||
* `Issue #218`_: Improved documentation on behavior of `package_data` and
|
||||
`include_package_data`. Files indicated by `package_data` are now included
|
||||
in the manifest.
|
||||
* `distribute_setup.py` now allows a `--download-base` argument for retrieving
|
||||
distribute from a specified location.
|
||||
|
||||
------
|
||||
0.6.28
|
||||
------
|
||||
|
||||
* `Issue #294`_: setup.py can now be invoked from any directory.
|
||||
* Scripts are now installed honoring the umask.
|
||||
* Added support for .dist-info directories.
|
||||
* `Issue #283`_: Fix and disable scanning of `*.pyc` / `*.pyo` files on
|
||||
Python 3.3.
|
||||
|
||||
------
|
||||
0.6.27
|
||||
------
|
||||
|
||||
* Support current snapshots of CPython 3.3.
|
||||
* Distribute now recognizes README.rst as a standard, default readme file.
|
||||
* Exclude 'encodings' modules when removing modules from sys.modules.
|
||||
Workaround for #285.
|
||||
* `Issue #231`_: Don't fiddle with system python when used with buildout
|
||||
(bootstrap.py)
|
||||
|
||||
------
|
||||
0.6.26
|
||||
------
|
||||
|
||||
* `Issue #183`_: Symlinked files are now extracted from source distributions.
|
||||
* `Issue #227`_: Easy_install fetch parameters are now passed during the
|
||||
installation of a source distribution; now fulfillment of setup_requires
|
||||
dependencies will honor the parameters passed to easy_install.
|
||||
|
||||
------
|
||||
0.6.25
|
||||
------
|
||||
|
||||
* `Issue #258`_: Workaround a cache issue
|
||||
* `Issue #260`_: distribute_setup.py now accepts the --user parameter for
|
||||
Python 2.6 and later.
|
||||
* `Issue #262`_: package_index.open_with_auth no longer throws LookupError
|
||||
on Python 3.
|
||||
* `Issue #269`_: AttributeError when an exception occurs reading Manifest.in
|
||||
on late releases of Python.
|
||||
* `Issue #272`_: Prevent TypeError when namespace package names are unicode
|
||||
and single-install-externally-managed is used. Also fixes PIP `issue
|
||||
449`_.
|
||||
* `Issue #273`_: Legacy script launchers now install with Python2/3 support.
|
||||
|
||||
------
|
||||
0.6.24
|
||||
------
|
||||
|
||||
* `Issue #249`_: Added options to exclude 2to3 fixers
|
||||
|
||||
------
|
||||
0.6.23
|
||||
------
|
||||
|
||||
* `Issue #244`_: Fixed a test
|
||||
* `Issue #243`_: Fixed a test
|
||||
* `Issue #239`_: Fixed a test
|
||||
* `Issue #240`_: Fixed a test
|
||||
* `Issue #241`_: Fixed a test
|
||||
* `Issue #237`_: Fixed a test
|
||||
* `Issue #238`_: easy_install now uses 64bit executable wrappers on 64bit Python
|
||||
* `Issue #208`_: Fixed parsed_versions, it now honors post-releases as noted in the documentation
|
||||
* `Issue #207`_: Windows cli and gui wrappers pass CTRL-C to child python process
|
||||
* `Issue #227`_: easy_install now passes its arguments to setup.py bdist_egg
|
||||
* `Issue #225`_: Fixed a NameError on Python 2.5, 2.4
|
||||
|
||||
------
|
||||
0.6.21
|
||||
------
|
||||
|
||||
* `Issue #225`_: FIxed a regression on py2.4
|
||||
|
||||
------
|
||||
0.6.20
|
||||
------
|
||||
|
||||
* `Issue #135`_: Include url in warning when processing URLs in package_index.
|
||||
* `Issue #212`_: Fix issue where easy_instal fails on Python 3 on windows installer.
|
||||
* `Issue #213`_: Fix typo in documentation.
|
||||
|
||||
------
|
||||
0.6.19
|
||||
------
|
||||
|
||||
* `Issue 206`_: AttributeError: 'HTTPMessage' object has no attribute 'getheaders'
|
||||
|
||||
------
|
||||
0.6.18
|
||||
------
|
||||
|
||||
* `Issue 210`_: Fixed a regression introduced by `Issue 204`_ fix.
|
||||
|
||||
------
|
||||
0.6.17
|
||||
------
|
||||
|
||||
* Support 'DISTRIBUTE_DISABLE_VERSIONED_EASY_INSTALL_SCRIPT' environment
|
||||
variable to allow to disable installation of easy_install-${version} script.
|
||||
* Support Python >=3.1.4 and >=3.2.1.
|
||||
* `Issue 204`_: Don't try to import the parent of a namespace package in
|
||||
declare_namespace
|
||||
* `Issue 196`_: Tolerate responses with multiple Content-Length headers
|
||||
* `Issue 205`_: Sandboxing doesn't preserve working_set. Leads to setup_requires
|
||||
problems.
|
||||
|
||||
------
|
||||
0.6.16
|
||||
------
|
||||
|
||||
* Builds sdist gztar even on Windows (avoiding `Issue 193`_).
|
||||
* `Issue 192`_: Fixed metadata omitted on Windows when package_dir
|
||||
specified with forward-slash.
|
||||
* `Issue 195`_: Cython build support.
|
||||
* `Issue 200`_: Issues with recognizing 64-bit packages on Windows.
|
||||
|
||||
------
|
||||
0.6.15
|
||||
------
|
||||
|
||||
* Fixed typo in bdist_egg
|
||||
* Several issues under Python 3 has been solved.
|
||||
* `Issue 146`_: Fixed missing DLL files after easy_install of windows exe package.
|
||||
|
||||
------
|
||||
0.6.14
|
||||
------
|
||||
|
||||
* `Issue 170`_: Fixed unittest failure. Thanks to Toshio.
|
||||
* `Issue 171`_: Fixed race condition in unittests cause deadlocks in test suite.
|
||||
* `Issue 143`_: Fixed a lookup issue with easy_install.
|
||||
Thanks to David and Zooko.
|
||||
* `Issue 174`_: Fixed the edit mode when its used with setuptools itself
|
||||
|
||||
------
|
||||
0.6.13
|
||||
------
|
||||
|
||||
* `Issue 160`_: 2.7 gives ValueError("Invalid IPv6 URL")
|
||||
* `Issue 150`_: Fixed using ~/.local even in a --no-site-packages virtualenv
|
||||
* `Issue 163`_: scan index links before external links, and don't use the md5 when
|
||||
comparing two distributions
|
||||
|
||||
------
|
||||
0.6.12
|
||||
------
|
||||
|
||||
* `Issue 149`_: Fixed various failures on 2.3/2.4
|
||||
|
||||
------
|
||||
0.6.11
|
||||
------
|
||||
|
||||
* Found another case of SandboxViolation - fixed
|
||||
* `Issue 15`_ and 48: Introduced a socket timeout of 15 seconds on url openings
|
||||
* Added indexsidebar.html into MANIFEST.in
|
||||
* `Issue 108`_: Fixed TypeError with Python3.1
|
||||
* `Issue 121`_: Fixed --help install command trying to actually install.
|
||||
* `Issue 112`_: Added an os.makedirs so that Tarek's solution will work.
|
||||
* `Issue 133`_: Added --no-find-links to easy_install
|
||||
* Added easy_install --user
|
||||
* `Issue 100`_: Fixed develop --user not taking '.' in PYTHONPATH into account
|
||||
* `Issue 134`_: removed spurious UserWarnings. Patch by VanLindberg
|
||||
* `Issue 138`_: cant_write_to_target error when setup_requires is used.
|
||||
* `Issue 147`_: respect the sys.dont_write_bytecode flag
|
||||
|
||||
------
|
||||
0.6.10
|
||||
------
|
||||
|
||||
* Reverted change made for the DistributionNotFound exception because
|
||||
zc.buildout uses the exception message to get the name of the
|
||||
distribution.
|
||||
|
||||
-----
|
||||
0.6.9
|
||||
-----
|
||||
|
||||
* `Issue 90`_: unknown setuptools version can be added in the working set
|
||||
* `Issue 87`_: setupt.py doesn't try to convert distribute_setup.py anymore
|
||||
Initial Patch by arfrever.
|
||||
* `Issue 89`_: added a side bar with a download link to the doc.
|
||||
* `Issue 86`_: fixed missing sentence in pkg_resources doc.
|
||||
* Added a nicer error message when a DistributionNotFound is raised.
|
||||
* `Issue 80`_: test_develop now works with Python 3.1
|
||||
* `Issue 93`_: upload_docs now works if there is an empty sub-directory.
|
||||
* `Issue 70`_: exec bit on non-exec files
|
||||
* `Issue 99`_: now the standalone easy_install command doesn't uses a
|
||||
"setup.cfg" if any exists in the working directory. It will use it
|
||||
only if triggered by ``install_requires`` from a setup.py call
|
||||
(install, develop, etc).
|
||||
* `Issue 101`_: Allowing ``os.devnull`` in Sandbox
|
||||
* `Issue 92`_: Fixed the "no eggs" found error with MacPort
|
||||
(platform.mac_ver() fails)
|
||||
* `Issue 103`_: test_get_script_header_jython_workaround not run
|
||||
anymore under py3 with C or POSIX local. Contributed by Arfrever.
|
||||
* `Issue 104`_: remvoved the assertion when the installation fails,
|
||||
with a nicer message for the end user.
|
||||
* `Issue 100`_: making sure there's no SandboxViolation when
|
||||
the setup script patches setuptools.
|
||||
|
||||
-----
|
||||
0.6.8
|
||||
-----
|
||||
|
||||
* Added "check_packages" in dist. (added in Setuptools 0.6c11)
|
||||
* Fixed the DONT_PATCH_SETUPTOOLS state.
|
||||
|
||||
-----
|
||||
0.6.7
|
||||
-----
|
||||
|
||||
* `Issue 58`_: Added --user support to the develop command
|
||||
* `Issue 11`_: Generated scripts now wrap their call to the script entry point
|
||||
in the standard "if name == 'main'"
|
||||
* Added the 'DONT_PATCH_SETUPTOOLS' environment variable, so virtualenv
|
||||
can drive an installation that doesn't patch a global setuptools.
|
||||
* Reviewed unladen-swallow specific change from
|
||||
http://code.google.com/p/unladen-swallow/source/detail?spec=svn875&r=719
|
||||
and determined that it no longer applies. Distribute should work fine with
|
||||
Unladen Swallow 2009Q3.
|
||||
* `Issue 21`_: Allow PackageIndex.open_url to gracefully handle all cases of a
|
||||
httplib.HTTPException instead of just InvalidURL and BadStatusLine.
|
||||
* Removed virtual-python.py from this distribution and updated documentation
|
||||
to point to the actively maintained virtualenv instead.
|
||||
* `Issue 64`_: use_setuptools no longer rebuilds the distribute egg every
|
||||
time it is run
|
||||
* use_setuptools now properly respects the requested version
|
||||
* use_setuptools will no longer try to import a distribute egg for the
|
||||
wrong Python version
|
||||
* `Issue 74`_: no_fake should be True by default.
|
||||
* `Issue 72`_: avoid a bootstrapping issue with easy_install -U
|
||||
|
||||
-----
|
||||
0.6.6
|
||||
-----
|
||||
|
||||
* Unified the bootstrap file so it works on both py2.x and py3k without 2to3
|
||||
(patch by Holger Krekel)
|
||||
|
||||
-----
|
||||
0.6.5
|
||||
-----
|
||||
|
||||
* `Issue 65`_: cli.exe and gui.exe are now generated at build time,
|
||||
depending on the platform in use.
|
||||
|
||||
* `Issue 67`_: Fixed doc typo (PEP 381/382)
|
||||
|
||||
* Distribute no longer shadows setuptools if we require a 0.7-series
|
||||
setuptools. And an error is raised when installing a 0.7 setuptools with
|
||||
distribute.
|
||||
|
||||
* When run from within buildout, no attempt is made to modify an existing
|
||||
setuptools egg, whether in a shared egg directory or a system setuptools.
|
||||
|
||||
* Fixed a hole in sandboxing allowing builtin file to write outside of
|
||||
the sandbox.
|
||||
|
||||
-----
|
||||
0.6.4
|
||||
-----
|
||||
|
||||
* Added the generation of `distribute_setup_3k.py` during the release.
|
||||
This closes `issue #52`_.
|
||||
|
||||
* Added an upload_docs command to easily upload project documentation to
|
||||
PyPI's http://packages.python.org. This close `issue #56`_.
|
||||
|
||||
* Fixed a bootstrap bug on the use_setuptools() API.
|
||||
|
||||
-----
|
||||
0.6.3
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Fixed a bunch of calls to file() that caused crashes on Python 3.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed a bug in sorting that caused bootstrap to fail on Python 3.
|
||||
|
||||
-----
|
||||
0.6.2
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Added Python 3 support; see docs/python3.txt.
|
||||
This closes http://bugs.python.org/setuptools/`issue39`_.
|
||||
|
||||
* Added option to run 2to3 automatically when installing on Python 3.
|
||||
This closes `issue #31`_.
|
||||
|
||||
* Fixed invalid usage of requirement.parse, that broke develop -d.
|
||||
This closes http://bugs.python.org/setuptools/`issue44`_.
|
||||
|
||||
* Fixed script launcher for 64-bit Windows.
|
||||
This closes http://bugs.python.org/setuptools/`issue2`_.
|
||||
|
||||
* KeyError when compiling extensions.
|
||||
This closes http://bugs.python.org/setuptools/`issue41`_.
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* Fixed bootstrap not working on Windows. This closes `issue #49`_.
|
||||
|
||||
* Fixed 2.6 dependencies. This closes `issue #50`_.
|
||||
|
||||
* Make sure setuptools is patched when running through easy_install
|
||||
This closes http://bugs.python.org/setuptools/`issue40`_.
|
||||
|
||||
-----
|
||||
0.6.1
|
||||
-----
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* package_index.urlopen now catches BadStatusLine and malformed url errors.
|
||||
This closes `issue #16`_ and `issue #18`_.
|
||||
|
||||
* zip_ok is now False by default. This closes
|
||||
http://bugs.python.org/setuptools/`issue33`_.
|
||||
|
||||
* Fixed invalid URL error catching. http://bugs.python.org/setuptools/`issue20`_.
|
||||
|
||||
* Fixed invalid bootstraping with easy_install installation (`issue #40`_).
|
||||
Thanks to Florian Schulze for the help.
|
||||
|
||||
* Removed buildout/bootstrap.py. A new repository will create a specific
|
||||
bootstrap.py script.
|
||||
|
||||
|
||||
bootstrapping
|
||||
=============
|
||||
|
||||
* The boostrap process leave setuptools alone if detected in the system
|
||||
and --root or --prefix is provided, but is not in the same location.
|
||||
This closes `issue #10`_.
|
||||
|
||||
---
|
||||
0.6
|
||||
---
|
||||
|
||||
setuptools
|
||||
==========
|
||||
|
||||
* Packages required at build time where not fully present at install time.
|
||||
This closes `issue #12`_.
|
||||
|
||||
* Protected against failures in tarfile extraction. This closes `issue #10`_.
|
||||
|
||||
* Made Jython api_tests.txt doctest compatible. This closes `issue #7`_.
|
||||
|
||||
* sandbox.py replaced builtin type file with builtin function open. This
|
||||
closes `issue #6`_.
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
* Added compatibility with Subversion 1.6. This references `issue #1`_.
|
||||
|
||||
pkg_resources
|
||||
=============
|
||||
|
||||
* Avoid a call to /usr/bin/sw_vers on OSX and use the official platform API
|
||||
instead. Based on a patch from ronaldoussoren. This closes `issue #5`_.
|
||||
|
||||
* Fixed a SandboxViolation for mkdir that could occur in certain cases.
|
||||
This closes `issue #13`_.
|
||||
|
||||
* Allow to find_on_path on systems with tight permissions to fail gracefully.
|
||||
This closes `issue #9`_.
|
||||
|
||||
* Corrected inconsistency between documentation and code of add_entry.
|
||||
This closes `issue #8`_.
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
easy_install
|
||||
============
|
||||
|
||||
* Immediately close all file handles. This closes `issue #3`_.
|
||||
|
||||
|
||||
.. _`Issue #135`: http://bitbucket.org/tarek/distribute/issue/135
|
||||
.. _`Issue #183`: http://bitbucket.org/tarek/distribute/issue/183
|
||||
.. _`Issue #207`: http://bitbucket.org/tarek/distribute/issue/207
|
||||
.. _`Issue #208`: http://bitbucket.org/tarek/distribute/issue/208
|
||||
.. _`Issue #212`: http://bitbucket.org/tarek/distribute/issue/212
|
||||
.. _`Issue #213`: http://bitbucket.org/tarek/distribute/issue/213
|
||||
.. _`Issue #218`: http://bitbucket.org/tarek/distribute/issue/218
|
||||
.. _`Issue #225`: http://bitbucket.org/tarek/distribute/issue/225
|
||||
.. _`Issue #227`: http://bitbucket.org/tarek/distribute/issue/227
|
||||
.. _`Issue #231`: http://bitbucket.org/tarek/distribute/issue/231
|
||||
.. _`Issue #237`: http://bitbucket.org/tarek/distribute/issue/237
|
||||
.. _`Issue #238`: http://bitbucket.org/tarek/distribute/issue/238
|
||||
.. _`Issue #239`: http://bitbucket.org/tarek/distribute/issue/239
|
||||
.. _`Issue #240`: http://bitbucket.org/tarek/distribute/issue/240
|
||||
.. _`Issue #241`: http://bitbucket.org/tarek/distribute/issue/241
|
||||
.. _`Issue #243`: http://bitbucket.org/tarek/distribute/issue/243
|
||||
.. _`Issue #244`: http://bitbucket.org/tarek/distribute/issue/244
|
||||
.. _`Issue #249`: http://bitbucket.org/tarek/distribute/issue/249
|
||||
.. _`Issue #258`: http://bitbucket.org/tarek/distribute/issue/258
|
||||
.. _`Issue #260`: http://bitbucket.org/tarek/distribute/issue/260
|
||||
.. _`Issue #262`: http://bitbucket.org/tarek/distribute/issue/262
|
||||
.. _`Issue #269`: http://bitbucket.org/tarek/distribute/issue/269
|
||||
.. _`Issue #272`: http://bitbucket.org/tarek/distribute/issue/272
|
||||
.. _`Issue #273`: http://bitbucket.org/tarek/distribute/issue/273
|
||||
.. _`Issue #283`: http://bitbucket.org/tarek/distribute/issue/283
|
||||
.. _`Issue #294`: http://bitbucket.org/tarek/distribute/issue/294
|
||||
.. _`Issue #299`: http://bitbucket.org/tarek/distribute/issue/299
|
||||
.. _`Issue #301`: http://bitbucket.org/tarek/distribute/issue/301
|
||||
.. _`Issue #303`: http://bitbucket.org/tarek/distribute/issue/303
|
||||
.. _`Issue #304`: http://bitbucket.org/tarek/distribute/issue/304
|
||||
.. _`Issue #305`: http://bitbucket.org/tarek/distribute/issue/305
|
||||
.. _`Issue #306`: http://bitbucket.org/tarek/distribute/issue/306
|
||||
.. _`Issue #307`: http://bitbucket.org/tarek/distribute/issue/307
|
||||
.. _`Issue #310`: http://bitbucket.org/tarek/distribute/issue/310
|
||||
.. _`Issue #311`: http://bitbucket.org/tarek/distribute/issue/311
|
||||
.. _`Issue #313`: http://bitbucket.org/tarek/distribute/issue/313
|
||||
.. _`Issue #314`: http://bitbucket.org/tarek/distribute/issue/314
|
||||
.. _`Issue #320`: http://bitbucket.org/tarek/distribute/issue/320
|
||||
.. _`Issue #323`: http://bitbucket.org/tarek/distribute/issue/323
|
||||
.. _`Issue #326`: http://bitbucket.org/tarek/distribute/issue/326
|
||||
.. _`Issue #327`: http://bitbucket.org/tarek/distribute/issue/327
|
||||
.. _`Issue #328`: http://bitbucket.org/tarek/distribute/issue/328
|
||||
.. _`Issue #329`: http://bitbucket.org/tarek/distribute/issue/329
|
||||
.. _`Issue #334`: http://bitbucket.org/tarek/distribute/issue/334
|
||||
.. _`Issue #335`: http://bitbucket.org/tarek/distribute/issue/335
|
||||
.. _`Issue #336`: http://bitbucket.org/tarek/distribute/issue/336
|
||||
.. _`Issue #341`: http://bitbucket.org/tarek/distribute/issue/341
|
||||
.. _`Issue 100`: http://bitbucket.org/tarek/distribute/issue/100
|
||||
.. _`Issue 101`: http://bitbucket.org/tarek/distribute/issue/101
|
||||
.. _`Issue 103`: http://bitbucket.org/tarek/distribute/issue/103
|
||||
.. _`Issue 104`: http://bitbucket.org/tarek/distribute/issue/104
|
||||
.. _`Issue 108`: http://bitbucket.org/tarek/distribute/issue/108
|
||||
.. _`Issue 11`: http://bitbucket.org/tarek/distribute/issue/11
|
||||
.. _`Issue 112`: http://bitbucket.org/tarek/distribute/issue/112
|
||||
.. _`Issue 121`: http://bitbucket.org/tarek/distribute/issue/121
|
||||
.. _`Issue 133`: http://bitbucket.org/tarek/distribute/issue/133
|
||||
.. _`Issue 134`: http://bitbucket.org/tarek/distribute/issue/134
|
||||
.. _`Issue 138`: http://bitbucket.org/tarek/distribute/issue/138
|
||||
.. _`Issue 143`: http://bitbucket.org/tarek/distribute/issue/143
|
||||
.. _`Issue 146`: http://bitbucket.org/tarek/distribute/issue/146
|
||||
.. _`Issue 147`: http://bitbucket.org/tarek/distribute/issue/147
|
||||
.. _`Issue 149`: http://bitbucket.org/tarek/distribute/issue/149
|
||||
.. _`Issue 15`: http://bitbucket.org/tarek/distribute/issue/15
|
||||
.. _`Issue 150`: http://bitbucket.org/tarek/distribute/issue/150
|
||||
.. _`Issue 160`: http://bitbucket.org/tarek/distribute/issue/160
|
||||
.. _`Issue 163`: http://bitbucket.org/tarek/distribute/issue/163
|
||||
.. _`Issue 170`: http://bitbucket.org/tarek/distribute/issue/170
|
||||
.. _`Issue 171`: http://bitbucket.org/tarek/distribute/issue/171
|
||||
.. _`Issue 174`: http://bitbucket.org/tarek/distribute/issue/174
|
||||
.. _`Issue 192`: http://bitbucket.org/tarek/distribute/issue/192
|
||||
.. _`Issue 193`: http://bitbucket.org/tarek/distribute/issue/193
|
||||
.. _`Issue 195`: http://bitbucket.org/tarek/distribute/issue/195
|
||||
.. _`Issue 196`: http://bitbucket.org/tarek/distribute/issue/196
|
||||
.. _`Issue 200`: http://bitbucket.org/tarek/distribute/issue/200
|
||||
.. _`Issue 204`: http://bitbucket.org/tarek/distribute/issue/204
|
||||
.. _`Issue 205`: http://bitbucket.org/tarek/distribute/issue/205
|
||||
.. _`Issue 206`: http://bitbucket.org/tarek/distribute/issue/206
|
||||
.. _`Issue 21`: http://bitbucket.org/tarek/distribute/issue/21
|
||||
.. _`Issue 210`: http://bitbucket.org/tarek/distribute/issue/210
|
||||
.. _`Issue 58`: http://bitbucket.org/tarek/distribute/issue/58
|
||||
.. _`Issue 64`: http://bitbucket.org/tarek/distribute/issue/64
|
||||
.. _`Issue 65`: http://bitbucket.org/tarek/distribute/issue/65
|
||||
.. _`Issue 67`: http://bitbucket.org/tarek/distribute/issue/67
|
||||
.. _`Issue 70`: http://bitbucket.org/tarek/distribute/issue/70
|
||||
.. _`Issue 72`: http://bitbucket.org/tarek/distribute/issue/72
|
||||
.. _`Issue 74`: http://bitbucket.org/tarek/distribute/issue/74
|
||||
.. _`Issue 80`: http://bitbucket.org/tarek/distribute/issue/80
|
||||
.. _`Issue 86`: http://bitbucket.org/tarek/distribute/issue/86
|
||||
.. _`Issue 87`: http://bitbucket.org/tarek/distribute/issue/87
|
||||
.. _`Issue 89`: http://bitbucket.org/tarek/distribute/issue/89
|
||||
.. _`Issue 90`: http://bitbucket.org/tarek/distribute/issue/90
|
||||
.. _`Issue 92`: http://bitbucket.org/tarek/distribute/issue/92
|
||||
.. _`Issue 93`: http://bitbucket.org/tarek/distribute/issue/93
|
||||
.. _`Issue 99`: http://bitbucket.org/tarek/distribute/issue/99
|
||||
.. _`issue
|
||||
449`: http://bitbucket.org/tarek/distribute/issue/449
|
||||
.. _`issue #1`: http://bitbucket.org/tarek/distribute/issue/1
|
||||
.. _`issue #10`: http://bitbucket.org/tarek/distribute/issue/10
|
||||
.. _`issue #12`: http://bitbucket.org/tarek/distribute/issue/12
|
||||
.. _`issue #13`: http://bitbucket.org/tarek/distribute/issue/13
|
||||
.. _`issue #16`: http://bitbucket.org/tarek/distribute/issue/16
|
||||
.. _`issue #18`: http://bitbucket.org/tarek/distribute/issue/18
|
||||
.. _`issue #3`: http://bitbucket.org/tarek/distribute/issue/3
|
||||
.. _`issue #31`: http://bitbucket.org/tarek/distribute/issue/31
|
||||
.. _`issue #40`: http://bitbucket.org/tarek/distribute/issue/40
|
||||
.. _`issue #49`: http://bitbucket.org/tarek/distribute/issue/49
|
||||
.. _`issue #5`: http://bitbucket.org/tarek/distribute/issue/5
|
||||
.. _`issue #50`: http://bitbucket.org/tarek/distribute/issue/50
|
||||
.. _`issue #52`: http://bitbucket.org/tarek/distribute/issue/52
|
||||
.. _`issue #56`: http://bitbucket.org/tarek/distribute/issue/56
|
||||
.. _`issue #6`: http://bitbucket.org/tarek/distribute/issue/6
|
||||
.. _`issue #7`: http://bitbucket.org/tarek/distribute/issue/7
|
||||
.. _`issue #8`: http://bitbucket.org/tarek/distribute/issue/8
|
||||
.. _`issue #9`: http://bitbucket.org/tarek/distribute/issue/9
|
||||
.. _`issue1980`: http://bitbucket.org/tarek/distribute/issue/1980
|
||||
.. _`issue1981`: http://bitbucket.org/tarek/distribute/issue/1981
|
||||
.. _`issue2`: http://bitbucket.org/tarek/distribute/issue/2
|
||||
.. _`issue20`: http://bitbucket.org/tarek/distribute/issue/20
|
||||
.. _`issue33`: http://bitbucket.org/tarek/distribute/issue/33
|
||||
.. _`issue39`: http://bitbucket.org/tarek/distribute/issue/39
|
||||
.. _`issue40`: http://bitbucket.org/tarek/distribute/issue/40
|
||||
.. _`issue41`: http://bitbucket.org/tarek/distribute/issue/41
|
||||
.. _`issue44`: http://bitbucket.org/tarek/distribute/issue/44
|
||||
|
||||
|
||||
Keywords: CPAN PyPI distutils eggs package management
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Python Software Foundation License
|
||||
Classifier: License :: OSI Approved :: Zope Public License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 2.4
|
||||
Classifier: Programming Language :: Python :: 2.5
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.1
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: System :: Archiving :: Packaging
|
||||
Classifier: Topic :: System :: Systems Administration
|
||||
Classifier: Topic :: Utilities
|
||||
-546
@@ -1,546 +0,0 @@
|
||||
#!python
|
||||
"""Bootstrap distribute installation
|
||||
|
||||
If you want to use setuptools in your package's setup.py, just include this
|
||||
file in the same directory with it, and add this to the top of your setup.py::
|
||||
|
||||
from distribute_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
If you want to require a specific version of setuptools, set a download
|
||||
mirror, or use an alternate download directory, you can do so by supplying
|
||||
the appropriate options to ``use_setuptools()``.
|
||||
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import fnmatch
|
||||
import tempfile
|
||||
import tarfile
|
||||
import optparse
|
||||
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from site import USER_SITE
|
||||
except ImportError:
|
||||
USER_SITE = None
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
return subprocess.call(args) == 0
|
||||
|
||||
except ImportError:
|
||||
# will be used for python 2.3
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
# quoting arguments if windows
|
||||
if sys.platform == 'win32':
|
||||
def quote(arg):
|
||||
if ' ' in arg:
|
||||
return '"%s"' % arg
|
||||
return arg
|
||||
args = [quote(arg) for arg in args]
|
||||
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||
|
||||
DEFAULT_VERSION = "0.6.34"
|
||||
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||
|
||||
SETUPTOOLS_PKG_INFO = """\
|
||||
Metadata-Version: 1.0
|
||||
Name: setuptools
|
||||
Version: %s
|
||||
Summary: xxxx
|
||||
Home-page: xxx
|
||||
Author: xxx
|
||||
Author-email: xxx
|
||||
License: xxx
|
||||
Description: xxx
|
||||
""" % SETUPTOOLS_FAKED_VERSION
|
||||
|
||||
|
||||
def _install(tarball, install_args=()):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# installing
|
||||
log.warn('Installing Distribute')
|
||||
if not _python_cmd('setup.py', 'install', *install_args):
|
||||
log.warn('Something went wrong during the installation.')
|
||||
log.warn('See the error message above.')
|
||||
# exitcode will be 2
|
||||
return 2
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
def _build_egg(egg, tarball, to_dir):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# building an egg
|
||||
log.warn('Building a Distribute egg in %s', to_dir)
|
||||
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
# returning the result
|
||||
log.warn(egg)
|
||||
if not os.path.exists(egg):
|
||||
raise IOError('Could not build the egg.')
|
||||
|
||||
|
||||
def _do_download(version, download_base, to_dir, download_delay):
|
||||
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||
% (version, sys.version_info[0], sys.version_info[1]))
|
||||
if not os.path.exists(egg):
|
||||
tarball = download_setuptools(version, download_base,
|
||||
to_dir, download_delay)
|
||||
_build_egg(egg, tarball, to_dir)
|
||||
sys.path.insert(0, egg)
|
||||
import setuptools
|
||||
setuptools.bootstrap_install_from = egg
|
||||
|
||||
|
||||
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
was_imported = 'pkg_resources' in sys.modules or \
|
||||
'setuptools' in sys.modules
|
||||
try:
|
||||
try:
|
||||
import pkg_resources
|
||||
if not hasattr(pkg_resources, '_distribute'):
|
||||
if not no_fake:
|
||||
_fake_setuptools()
|
||||
raise ImportError
|
||||
except ImportError:
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
try:
|
||||
pkg_resources.require("distribute>=" + version)
|
||||
return
|
||||
except pkg_resources.VersionConflict:
|
||||
e = sys.exc_info()[1]
|
||||
if was_imported:
|
||||
sys.stderr.write(
|
||||
"The required version of distribute (>=%s) is not available,\n"
|
||||
"and can't be installed while this script is running. Please\n"
|
||||
"install a more recent version first, using\n"
|
||||
"'easy_install -U distribute'."
|
||||
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||
sys.exit(2)
|
||||
else:
|
||||
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
except pkg_resources.DistributionNotFound:
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
finally:
|
||||
if not no_fake:
|
||||
_create_fake_setuptools_pkg_info(to_dir)
|
||||
|
||||
|
||||
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, delay=15):
|
||||
"""Download distribute from a specified location and return its filename
|
||||
|
||||
`version` should be a valid distribute version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download
|
||||
attempt.
|
||||
"""
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
tgz_name = "distribute-%s.tar.gz" % version
|
||||
url = download_base + tgz_name
|
||||
saveto = os.path.join(to_dir, tgz_name)
|
||||
src = dst = None
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
try:
|
||||
log.warn("Downloading %s", url)
|
||||
src = urlopen(url)
|
||||
# Read/write all in one block, so we don't create a corrupt file
|
||||
# if the download is interrupted.
|
||||
data = src.read()
|
||||
dst = open(saveto, "wb")
|
||||
dst.write(data)
|
||||
finally:
|
||||
if src:
|
||||
src.close()
|
||||
if dst:
|
||||
dst.close()
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
|
||||
def _no_sandbox(function):
|
||||
def __no_sandbox(*args, **kw):
|
||||
try:
|
||||
from setuptools.sandbox import DirectorySandbox
|
||||
if not hasattr(DirectorySandbox, '_old'):
|
||||
def violation(*args):
|
||||
pass
|
||||
DirectorySandbox._old = DirectorySandbox._violation
|
||||
DirectorySandbox._violation = violation
|
||||
patched = True
|
||||
else:
|
||||
patched = False
|
||||
except ImportError:
|
||||
patched = False
|
||||
|
||||
try:
|
||||
return function(*args, **kw)
|
||||
finally:
|
||||
if patched:
|
||||
DirectorySandbox._violation = DirectorySandbox._old
|
||||
del DirectorySandbox._old
|
||||
|
||||
return __no_sandbox
|
||||
|
||||
|
||||
def _patch_file(path, content):
|
||||
"""Will backup the file then patch it"""
|
||||
f = open(path)
|
||||
existing_content = f.read()
|
||||
f.close()
|
||||
if existing_content == content:
|
||||
# already patched
|
||||
log.warn('Already patched.')
|
||||
return False
|
||||
log.warn('Patching...')
|
||||
_rename_path(path)
|
||||
f = open(path, 'w')
|
||||
try:
|
||||
f.write(content)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
_patch_file = _no_sandbox(_patch_file)
|
||||
|
||||
|
||||
def _same_content(path, content):
|
||||
f = open(path)
|
||||
existing_content = f.read()
|
||||
f.close()
|
||||
return existing_content == content
|
||||
|
||||
|
||||
def _rename_path(path):
|
||||
new_name = path + '.OLD.%s' % time.time()
|
||||
log.warn('Renaming %s to %s', path, new_name)
|
||||
os.rename(path, new_name)
|
||||
return new_name
|
||||
|
||||
|
||||
def _remove_flat_installation(placeholder):
|
||||
if not os.path.isdir(placeholder):
|
||||
log.warn('Unkown installation at %s', placeholder)
|
||||
return False
|
||||
found = False
|
||||
for file in os.listdir(placeholder):
|
||||
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
log.warn('Could not locate setuptools*.egg-info')
|
||||
return
|
||||
|
||||
log.warn('Moving elements out of the way...')
|
||||
pkg_info = os.path.join(placeholder, file)
|
||||
if os.path.isdir(pkg_info):
|
||||
patched = _patch_egg_dir(pkg_info)
|
||||
else:
|
||||
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||
|
||||
if not patched:
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
# now let's move the files out of the way
|
||||
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||
element = os.path.join(placeholder, element)
|
||||
if os.path.exists(element):
|
||||
_rename_path(element)
|
||||
else:
|
||||
log.warn('Could not find the %s element of the '
|
||||
'Setuptools distribution', element)
|
||||
return True
|
||||
|
||||
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||
|
||||
|
||||
def _after_install(dist):
|
||||
log.warn('After install bootstrap.')
|
||||
placeholder = dist.get_command_obj('install').install_purelib
|
||||
_create_fake_setuptools_pkg_info(placeholder)
|
||||
|
||||
|
||||
def _create_fake_setuptools_pkg_info(placeholder):
|
||||
if not placeholder or not os.path.exists(placeholder):
|
||||
log.warn('Could not find the install location')
|
||||
return
|
||||
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||
if os.path.exists(pkg_info):
|
||||
log.warn('%s already exists', pkg_info)
|
||||
return
|
||||
|
||||
log.warn('Creating %s', pkg_info)
|
||||
try:
|
||||
f = open(pkg_info, 'w')
|
||||
except EnvironmentError:
|
||||
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||
return
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||
log.warn('Creating %s', pth_file)
|
||||
f = open(pth_file, 'w')
|
||||
try:
|
||||
f.write(os.path.join(os.curdir, setuptools_file))
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||
_create_fake_setuptools_pkg_info
|
||||
)
|
||||
|
||||
|
||||
def _patch_egg_dir(path):
|
||||
# let's check if it's already patched
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
if os.path.exists(pkg_info):
|
||||
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
_rename_path(path)
|
||||
os.mkdir(path)
|
||||
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
f = open(pkg_info, 'w')
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||
|
||||
|
||||
def _before_install():
|
||||
log.warn('Before install bootstrap.')
|
||||
_fake_setuptools()
|
||||
|
||||
|
||||
def _under_prefix(location):
|
||||
if 'install' not in sys.argv:
|
||||
return True
|
||||
args = sys.argv[sys.argv.index('install') + 1:]
|
||||
for index, arg in enumerate(args):
|
||||
for option in ('--root', '--prefix'):
|
||||
if arg.startswith('%s=' % option):
|
||||
top_dir = arg.split('root=')[-1]
|
||||
return location.startswith(top_dir)
|
||||
elif arg == option:
|
||||
if len(args) > index:
|
||||
top_dir = args[index + 1]
|
||||
return location.startswith(top_dir)
|
||||
if arg == '--user' and USER_SITE is not None:
|
||||
return location.startswith(USER_SITE)
|
||||
return True
|
||||
|
||||
|
||||
def _fake_setuptools():
|
||||
log.warn('Scanning installed packages')
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
# we're cool
|
||||
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||
return
|
||||
ws = pkg_resources.working_set
|
||||
try:
|
||||
setuptools_dist = ws.find(
|
||||
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||
)
|
||||
except TypeError:
|
||||
# old distribute API
|
||||
setuptools_dist = ws.find(
|
||||
pkg_resources.Requirement.parse('setuptools')
|
||||
)
|
||||
|
||||
if setuptools_dist is None:
|
||||
log.warn('No setuptools distribution found')
|
||||
return
|
||||
# detecting if it was already faked
|
||||
setuptools_location = setuptools_dist.location
|
||||
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||
|
||||
# if --root or --preix was provided, and if
|
||||
# setuptools is not located in them, we don't patch it
|
||||
if not _under_prefix(setuptools_location):
|
||||
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||
' in another location')
|
||||
return
|
||||
|
||||
# let's see if its an egg
|
||||
if not setuptools_location.endswith('.egg'):
|
||||
log.warn('Non-egg installation')
|
||||
res = _remove_flat_installation(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
else:
|
||||
log.warn('Egg installation')
|
||||
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||
if (os.path.exists(pkg_info) and
|
||||
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||
log.warn('Already patched.')
|
||||
return
|
||||
log.warn('Patching...')
|
||||
# let's create a fake egg replacing setuptools one
|
||||
res = _patch_egg_dir(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
log.warn('Patching complete.')
|
||||
_relaunch()
|
||||
|
||||
|
||||
def _relaunch():
|
||||
log.warn('Relaunching...')
|
||||
# we have to relaunch the process
|
||||
# pip marker to avoid a relaunch bug
|
||||
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||
_cmd2 = ['-c', 'install', '--record']
|
||||
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||
sys.argv[0] = 'setup.py'
|
||||
args = [sys.executable] + sys.argv
|
||||
sys.exit(subprocess.call(args))
|
||||
|
||||
|
||||
def _extractall(self, path=".", members=None):
|
||||
"""Extract all members from the archive to the current working
|
||||
directory and set owner, modification time and permissions on
|
||||
directories afterwards. `path' specifies a different directory
|
||||
to extract to. `members' is optional and must be a subset of the
|
||||
list returned by getmembers().
|
||||
"""
|
||||
import copy
|
||||
import operator
|
||||
from tarfile import ExtractError
|
||||
directories = []
|
||||
|
||||
if members is None:
|
||||
members = self
|
||||
|
||||
for tarinfo in members:
|
||||
if tarinfo.isdir():
|
||||
# Extract directories with a safe mode.
|
||||
directories.append(tarinfo)
|
||||
tarinfo = copy.copy(tarinfo)
|
||||
tarinfo.mode = 448 # decimal for oct 0700
|
||||
self.extract(tarinfo, path)
|
||||
|
||||
# Reverse sort directories.
|
||||
if sys.version_info < (2, 4):
|
||||
def sorter(dir1, dir2):
|
||||
return cmp(dir1.name, dir2.name)
|
||||
directories.sort(sorter)
|
||||
directories.reverse()
|
||||
else:
|
||||
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||
|
||||
# Set correct owner, mtime and filemode on directories.
|
||||
for tarinfo in directories:
|
||||
dirpath = os.path.join(path, tarinfo.name)
|
||||
try:
|
||||
self.chown(tarinfo, dirpath)
|
||||
self.utime(tarinfo, dirpath)
|
||||
self.chmod(tarinfo, dirpath)
|
||||
except ExtractError:
|
||||
e = sys.exc_info()[1]
|
||||
if self.errorlevel > 1:
|
||||
raise
|
||||
else:
|
||||
self._dbg(1, "tarfile: %s" % e)
|
||||
|
||||
|
||||
def _build_install_args(options):
|
||||
"""
|
||||
Build the arguments to 'python setup.py install' on the distribute package
|
||||
"""
|
||||
install_args = []
|
||||
if options.user_install:
|
||||
if sys.version_info < (2, 6):
|
||||
log.warn("--user requires Python 2.6 or later")
|
||||
raise SystemExit(1)
|
||||
install_args.append('--user')
|
||||
return install_args
|
||||
|
||||
def _parse_args():
|
||||
"""
|
||||
Parse the command line for options
|
||||
"""
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option(
|
||||
'--user', dest='user_install', action='store_true', default=False,
|
||||
help='install in user site package (requires Python 2.6 or later)')
|
||||
parser.add_option(
|
||||
'--download-base', dest='download_base', metavar="URL",
|
||||
default=DEFAULT_URL,
|
||||
help='alternative URL from where to download the distribute package')
|
||||
options, args = parser.parse_args()
|
||||
# positional arguments are ignored
|
||||
return options
|
||||
|
||||
def main(version=DEFAULT_VERSION):
|
||||
"""Install or upgrade setuptools and EasyInstall"""
|
||||
options = _parse_args()
|
||||
tarball = download_setuptools(download_base=options.download_base)
|
||||
return _install(tarball, _build_install_args(options))
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -1,8 +0,0 @@
|
||||
<h3>Download</h3>
|
||||
|
||||
<p>Current version: <b>{{ version }}</b></p>
|
||||
<p>Get Distribute from the <a href="http://pypi.python.org/pypi/distribute"> Python Package Index</a>
|
||||
|
||||
<h3>Questions? Suggestions? Contributions?</h3>
|
||||
|
||||
<p>Visit the <a href="http://bitbucket.org/tarek/distribute">Distribute project page</a> </p>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
Welcome to Distribute's documentation!
|
||||
======================================
|
||||
|
||||
`Distribute` is a fork of the `Setuptools` project.
|
||||
|
||||
Distribute is intended to replace Setuptools as the standard method for
|
||||
working with Python module distributions.
|
||||
|
||||
For those who may wonder why they should switch to Distribute over Setuptools, it’s quite simple:
|
||||
|
||||
- Distribute is a drop-in replacement for Setuptools
|
||||
- The code is actively maintained, and has over 10 commiters
|
||||
- Distribute offers Python 3 support !
|
||||
|
||||
Documentation content:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
roadmap
|
||||
python3
|
||||
using
|
||||
setuptools
|
||||
easy_install
|
||||
pkg_resources
|
||||
|
||||
|
||||
.. image:: http://python-distribute.org/pip_distribute.png
|
||||
|
||||
Design done by Idan Gazit (http://pixane.com) - License: cc-by-3.0
|
||||
|
||||
Copy & paste::
|
||||
|
||||
curl -O http://python-distribute.org/distribute_setup.py
|
||||
python distribute_setup.py
|
||||
easy_install pip
|
||||
@@ -1,121 +0,0 @@
|
||||
=====================================================
|
||||
Supporting both Python 2 and Python 3 with Distribute
|
||||
=====================================================
|
||||
|
||||
Starting with version 0.6.2, Distribute supports Python 3. Installing and
|
||||
using distribute for Python 3 code works exactly the same as for Python 2
|
||||
code, but Distribute also helps you to support Python 2 and Python 3 from
|
||||
the same source code by letting you run 2to3 on the code as a part of the
|
||||
build process, by setting the keyword parameter ``use_2to3`` to True.
|
||||
|
||||
|
||||
Distribute as help during porting
|
||||
=================================
|
||||
|
||||
Distribute can make the porting process much easier by automatically running
|
||||
2to3 as a part of the test running. To do this you need to configure the
|
||||
setup.py so that you can run the unit tests with ``python setup.py test``.
|
||||
|
||||
See :ref:`test` for more information on this.
|
||||
|
||||
Once you have the tests running under Python 2, you can add the use_2to3
|
||||
keyword parameters to setup(), and start running the tests under Python 3.
|
||||
The test command will now first run the build command during which the code
|
||||
will be converted with 2to3, and the tests will then be run from the build
|
||||
directory, as opposed from the source directory as is normally done.
|
||||
|
||||
Distribute will convert all Python files, and also all doctests in Python
|
||||
files. However, if you have doctests located in separate text files, these
|
||||
will not automatically be converted. By adding them to the
|
||||
``convert_2to3_doctests`` keyword parameter Distrubute will convert them as
|
||||
well.
|
||||
|
||||
By default, the conversion uses all fixers in the ``lib2to3.fixers`` package.
|
||||
To use additional fixers, the parameter ``use_2to3_fixers`` can be set
|
||||
to a list of names of packages containing fixers. To exclude fixers, the
|
||||
parameter ``use_2to3_exclude_fixers`` can be set to fixer names to be
|
||||
skipped.
|
||||
|
||||
A typical setup.py can look something like this::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='your.module',
|
||||
version = '1.0',
|
||||
description='This is your awesome module',
|
||||
author='You',
|
||||
author_email='your@email',
|
||||
package_dir = {'': 'src'},
|
||||
packages = ['your', 'you.module'],
|
||||
test_suite = 'your.module.tests',
|
||||
use_2to3 = True,
|
||||
convert_2to3_doctests = ['src/your/module/README.txt'],
|
||||
use_2to3_fixers = ['your.fixers'],
|
||||
use_2to3_exclude_fixers = ['lib2to3.fixes.fix_import'],
|
||||
)
|
||||
|
||||
Differential conversion
|
||||
-----------------------
|
||||
|
||||
Note that a file will only be copied and converted during the build process
|
||||
if the source file has been changed. If you add a file to the doctests
|
||||
that should be converted, it will not be converted the next time you run
|
||||
the tests, since it hasn't been modified. You need to remove it from the
|
||||
build directory. Also if you run the build, install or test commands before
|
||||
adding the use_2to3 parameter, you will have to remove the build directory
|
||||
before you run the test command, as the files otherwise will seem updated,
|
||||
and no conversion will happen.
|
||||
|
||||
In general, if code doesn't seem to be converted, deleting the build directory
|
||||
and trying again is a good saferguard against the build directory getting
|
||||
"out of sync" with the source directory.
|
||||
|
||||
Distributing Python 3 modules
|
||||
=============================
|
||||
|
||||
You can distribute your modules with Python 3 support in different ways. A
|
||||
normal source distribution will work, but can be slow in installing, as the
|
||||
2to3 process will be run during the install. But you can also distribute
|
||||
the module in binary format, such as a binary egg. That egg will contain the
|
||||
already converted code, and hence no 2to3 conversion is needed during install.
|
||||
|
||||
Advanced features
|
||||
=================
|
||||
|
||||
If you don't want to run the 2to3 conversion on the doctests in Python files,
|
||||
you can turn that off by setting ``setuptools.use_2to3_on_doctests = False``.
|
||||
|
||||
Note on compatibility with setuptools
|
||||
=====================================
|
||||
|
||||
Setuptools do not know about the new keyword parameters to support Python 3.
|
||||
As a result it will warn about the unknown keyword parameters if you use
|
||||
setuptools instead of Distribute under Python 2. This is not an error, and
|
||||
install process will continue as normal, but if you want to get rid of that
|
||||
error this is easy. Simply conditionally add the new parameters into an extra
|
||||
dict and pass that dict into setup()::
|
||||
|
||||
from setuptools import setup
|
||||
import sys
|
||||
|
||||
extra = {}
|
||||
if sys.version_info >= (3,):
|
||||
extra['use_2to3'] = True
|
||||
extra['convert_2to3_doctests'] = ['src/your/module/README.txt']
|
||||
extra['use_2to3_fixers'] = ['your.fixers']
|
||||
|
||||
setup(
|
||||
name='your.module',
|
||||
version = '1.0',
|
||||
description='This is your awesome module',
|
||||
author='You',
|
||||
author_email='your@email',
|
||||
package_dir = {'': 'src'},
|
||||
packages = ['your', 'you.module'],
|
||||
test_suite = 'your.module.tests',
|
||||
**extra
|
||||
)
|
||||
|
||||
This way the parameters will only be used under Python 3, where you have to
|
||||
use Distribute.
|
||||
@@ -1,86 +0,0 @@
|
||||
=======
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
Distribute has two branches:
|
||||
|
||||
- 0.6.x : provides a Setuptools-0.6cX compatible version
|
||||
- 0.7.x : will provide a refactoring
|
||||
|
||||
0.6.x
|
||||
=====
|
||||
|
||||
Not "much" is going to happen here, we want this branch to be helpful
|
||||
to the community *today* by addressing the 40-or-so bugs
|
||||
that were found in Setuptools and never fixed. This is eventually
|
||||
happen soon because its development is
|
||||
fast : there are up to 5 commiters that are working on it very often
|
||||
(and the number grows weekly.)
|
||||
|
||||
The biggest issue with this branch is that it is providing the same
|
||||
packages and modules setuptools does, and this
|
||||
requires some bootstrapping work where we make sure once Distribute is
|
||||
installed, all Distribution that requires Setuptools
|
||||
will continue to work. This is done by faking the metadata of
|
||||
Setuptools 0.6c9. That's the only way we found to do this.
|
||||
|
||||
There's one major thing though: thanks to the work of Lennart, Alex,
|
||||
Martin, this branch supports Python 3,
|
||||
which is great to have to speed up Py3 adoption.
|
||||
|
||||
The goal of the 0.6.x is to remove as much bugs as we can, and try if
|
||||
possible to remove the patches done
|
||||
on Distutils. We will support 0.6.x maintenance for years and we will
|
||||
promote its usage everywhere instead of
|
||||
Setuptools.
|
||||
|
||||
Some new commands are added there, when they are helpful and don't
|
||||
interact with the rest. I am thinking
|
||||
about "upload_docs" that let you upload documentation to PyPI. The
|
||||
goal is to move it to Distutils
|
||||
at some point, if the documentation feature of PyPI stays and starts to be used.
|
||||
|
||||
0.7.x
|
||||
=====
|
||||
|
||||
We've started to refactor Distribute with this roadmap in mind (and
|
||||
no, as someone said, it's not vaporware,
|
||||
we've done a lot already)
|
||||
|
||||
- 0.7.x can be installed and used with 0.6.x
|
||||
|
||||
- easy_install is going to be deprecated ! use Pip !
|
||||
|
||||
- the version system will be deprecated, in favor of the one in Distutils
|
||||
|
||||
- no more Distutils monkey-patch that happens once you use the code
|
||||
(things like 'from distutils import cmd; cmd.Command = CustomCommand')
|
||||
|
||||
- no more custom site.py (that is: if something misses in Python's
|
||||
site.py we'll add it there instead of patching it)
|
||||
|
||||
- no more namespaced packages system, if PEP 382 (namespaces package
|
||||
support) makes it to 2.7
|
||||
|
||||
- The code is splitted in many packages and might be distributed under
|
||||
several distributions.
|
||||
|
||||
- distribute.resources: that's the old pkg_resources, but
|
||||
reorganized in clean, pep-8 modules. This package will
|
||||
only contain the query APIs and will focus on being PEP 376
|
||||
compatible. We will promote its usage and see if Pip wants
|
||||
to use it as a basis.
|
||||
It will probably shrink a lot though, once the stdlib provides PEP 376 support.
|
||||
|
||||
- distribute.entrypoints: that's the old pkg_resources entry points
|
||||
system, but on its own. it uses distribute.resources
|
||||
|
||||
- distribute.index: that's package_index and a few other things.
|
||||
everything required to interact with PyPI. We will promote
|
||||
its usage and see if Pip wants to use it as a basis.
|
||||
|
||||
- distribute.core (might be renamed to main): that's everything
|
||||
else, and uses the other packages.
|
||||
|
||||
Goal: A first release before (or when) Python 2.7 / 3.2 is out.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
================================
|
||||
Using Distribute in your project
|
||||
================================
|
||||
|
||||
To use Distribute in your project, the recommended way is to ship
|
||||
`distribute_setup.py` alongside your `setup.py` script and call
|
||||
it at the very begining of `setup.py` like this::
|
||||
|
||||
from distribute_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
Another way is to add ``Distribute`` in the ``install_requires`` option::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['distribute']
|
||||
)
|
||||
|
||||
|
||||
XXX to be finished
|
||||
@@ -1,540 +0,0 @@
|
||||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable dl, table.indextable dd {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px 7px 0 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px 7px 0 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition dl {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd p {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dt:target, .highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.refcount {
|
||||
color: #060;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 5px 0px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
tt.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #111111;
|
||||
color: #555555;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 300px;
|
||||
}
|
||||
|
||||
hr{
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 1em 30px 30px 30px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #555;
|
||||
width: 100%;
|
||||
padding: 13px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #6BA81E;
|
||||
line-height: 36px;
|
||||
color: #ffffff;
|
||||
text-shadow: 0px 1px 0 #444444;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #E2F3CC;
|
||||
}
|
||||
|
||||
div.related .right {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5em;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper{
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #222222;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
text-shadow: 1px 1px 0 white
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #888888;
|
||||
padding: 5px 20px;
|
||||
margin: 0.5em 0px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 10px 10px 20px;
|
||||
padding: 0;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
color: #E32E00;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #cccccc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.1em;
|
||||
padding: 0.15em 0.3em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input[type=text]{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #005B81;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #E32E00;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
color: #212224;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 5px 0 5px 0px;
|
||||
text-shadow: 0px 1px 0 white;
|
||||
border-bottom: 1px solid #C8D5E3;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 150%; }
|
||||
div.body h3 { font-size: 120%; }
|
||||
div.body h4 { font-size: 110%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.8em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.highlight{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eeeeee;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffffcc;
|
||||
border: 1px solid #ffff66;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #fafafa;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #ff6666;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
background-color: #fafafa;
|
||||
color: #222222;
|
||||
line-height: 1.5em;
|
||||
font-size: 1.1em;
|
||||
margin: 1.5em 0 1.5em 0;
|
||||
-webkit-box-shadow: 0px 0px 4px #d8d8d8;
|
||||
-moz-box-shadow: 0px 0px 4px #d8d8d8;
|
||||
box-shadow: 0px 0px 4px #d8d8d8;
|
||||
}
|
||||
|
||||
tt {
|
||||
color: #222222;
|
||||
padding: 1px 2px;
|
||||
font-size: 1.2em;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#table-of-contents ul {
|
||||
padding-left: 2em;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
.c { color: #999988; font-style: italic } /* Comment */
|
||||
.k { font-weight: bold } /* Keyword */
|
||||
.o { font-weight: bold } /* Operator */
|
||||
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
|
||||
.c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.ge { font-style: italic } /* Generic.Emph */
|
||||
.gr { color: #aa0000 } /* Generic.Error */
|
||||
.gh { color: #999999 } /* Generic.Heading */
|
||||
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.go { color: #111 } /* Generic.Output */
|
||||
.gp { color: #555555 } /* Generic.Prompt */
|
||||
.gs { font-weight: bold } /* Generic.Strong */
|
||||
.gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.kc { font-weight: bold } /* Keyword.Constant */
|
||||
.kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.m { color: #009999 } /* Literal.Number */
|
||||
.s { color: #bb8844 } /* Literal.String */
|
||||
.na { color: #008080 } /* Name.Attribute */
|
||||
.nb { color: #999999 } /* Name.Builtin */
|
||||
.nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.no { color: #ff99ff } /* Name.Constant */
|
||||
.ni { color: #800080 } /* Name.Entity */
|
||||
.ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.nn { color: #555555 } /* Name.Namespace */
|
||||
.nt { color: #000080 } /* Name.Tag */
|
||||
.nv { color: purple } /* Name.Variable */
|
||||
.ow { font-weight: bold } /* Operator.Word */
|
||||
.mf { color: #009999 } /* Literal.Number.Float */
|
||||
.mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.sb { color: #bb8844 } /* Literal.String.Backtick */
|
||||
.sc { color: #bb8844 } /* Literal.String.Char */
|
||||
.sd { color: #bb8844 } /* Literal.String.Doc */
|
||||
.s2 { color: #bb8844 } /* Literal.String.Double */
|
||||
.se { color: #bb8844 } /* Literal.String.Escape */
|
||||
.sh { color: #bb8844 } /* Literal.String.Heredoc */
|
||||
.si { color: #bb8844 } /* Literal.String.Interpol */
|
||||
.sx { color: #bb8844 } /* Literal.String.Other */
|
||||
.sr { color: #808000 } /* Literal.String.Regex */
|
||||
.s1 { color: #bb8844 } /* Literal.String.Single */
|
||||
.ss { color: #bb8844 } /* Literal.String.Symbol */
|
||||
.bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.vc { color: #ff99ff } /* Name.Variable.Class */
|
||||
.vg { color: #ff99ff } /* Name.Variable.Global */
|
||||
.vi { color: #ff99ff } /* Name.Variable.Instance */
|
||||
.il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
Welcome to Distribute's documentation!
|
||||
======================================
|
||||
|
||||
`Distribute` is a fork of the `Setuptools` project.
|
||||
|
||||
Distribute is intended to replace Setuptools as the standard method for
|
||||
working with Python module distributions.
|
||||
|
||||
For those who may wonder why they should switch to Distribute over Setuptools, it’s quite simple:
|
||||
|
||||
- Distribute is a drop-in replacement for Setuptools
|
||||
- The code is actively maintained, and has over 10 commiters
|
||||
- Distribute offers Python 3 support !
|
||||
|
||||
Documentation content:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
roadmap
|
||||
python3
|
||||
using
|
||||
setuptools
|
||||
easy_install
|
||||
pkg_resources
|
||||
|
||||
|
||||
.. image:: http://python-distribute.org/pip_distribute.png
|
||||
|
||||
Design done by Idan Gazit (http://pixane.com) - License: cc-by-3.0
|
||||
|
||||
Copy & paste::
|
||||
|
||||
curl -O http://python-distribute.org/distribute_setup.py
|
||||
python distribute_setup.py
|
||||
easy_install pip
|
||||
-1955
File diff suppressed because it is too large
Load Diff
-86
@@ -1,86 +0,0 @@
|
||||
=======
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
Distribute has two branches:
|
||||
|
||||
- 0.6.x : provides a Setuptools-0.6cX compatible version
|
||||
- 0.7.x : will provide a refactoring
|
||||
|
||||
0.6.x
|
||||
=====
|
||||
|
||||
Not "much" is going to happen here, we want this branch to be helpful
|
||||
to the community *today* by addressing the 40-or-so bugs
|
||||
that were found in Setuptools and never fixed. This is eventually
|
||||
happen soon because its development is
|
||||
fast : there are up to 5 commiters that are working on it very often
|
||||
(and the number grows weekly.)
|
||||
|
||||
The biggest issue with this branch is that it is providing the same
|
||||
packages and modules setuptools does, and this
|
||||
requires some bootstrapping work where we make sure once Distribute is
|
||||
installed, all Distribution that requires Setuptools
|
||||
will continue to work. This is done by faking the metadata of
|
||||
Setuptools 0.6c9. That's the only way we found to do this.
|
||||
|
||||
There's one major thing though: thanks to the work of Lennart, Alex,
|
||||
Martin, this branch supports Python 3,
|
||||
which is great to have to speed up Py3 adoption.
|
||||
|
||||
The goal of the 0.6.x is to remove as much bugs as we can, and try if
|
||||
possible to remove the patches done
|
||||
on Distutils. We will support 0.6.x maintenance for years and we will
|
||||
promote its usage everywhere instead of
|
||||
Setuptools.
|
||||
|
||||
Some new commands are added there, when they are helpful and don't
|
||||
interact with the rest. I am thinking
|
||||
about "upload_docs" that let you upload documentation to PyPI. The
|
||||
goal is to move it to Distutils
|
||||
at some point, if the documentation feature of PyPI stays and starts to be used.
|
||||
|
||||
0.7.x
|
||||
=====
|
||||
|
||||
We've started to refactor Distribute with this roadmap in mind (and
|
||||
no, as someone said, it's not vaporware,
|
||||
we've done a lot already)
|
||||
|
||||
- 0.7.x can be installed and used with 0.6.x
|
||||
|
||||
- easy_install is going to be deprecated ! use Pip !
|
||||
|
||||
- the version system will be deprecated, in favor of the one in Distutils
|
||||
|
||||
- no more Distutils monkey-patch that happens once you use the code
|
||||
(things like 'from distutils import cmd; cmd.Command = CustomCommand')
|
||||
|
||||
- no more custom site.py (that is: if something misses in Python's
|
||||
site.py we'll add it there instead of patching it)
|
||||
|
||||
- no more namespaced packages system, if PEP 382 (namespaces package
|
||||
support) makes it to 2.7
|
||||
|
||||
- The code is splitted in many packages and might be distributed under
|
||||
several distributions.
|
||||
|
||||
- distribute.resources: that's the old pkg_resources, but
|
||||
reorganized in clean, pep-8 modules. This package will
|
||||
only contain the query APIs and will focus on being PEP 376
|
||||
compatible. We will promote its usage and see if Pip wants
|
||||
to use it as a basis.
|
||||
It will probably shrink a lot though, once the stdlib provides PEP 376 support.
|
||||
|
||||
- distribute.entrypoints: that's the old pkg_resources entry points
|
||||
system, but on its own. it uses distribute.resources
|
||||
|
||||
- distribute.index: that's package_index and a few other things.
|
||||
everything required to interact with PyPI. We will promote
|
||||
its usage and see if Pip wants to use it as a basis.
|
||||
|
||||
- distribute.core (might be renamed to main): that's everything
|
||||
else, and uses the other packages.
|
||||
|
||||
Goal: A first release before (or when) Python 2.7 / 3.2 is out.
|
||||
|
||||
-3236
File diff suppressed because it is too large
Load Diff
-21
@@ -1,21 +0,0 @@
|
||||
================================
|
||||
Using Distribute in your project
|
||||
================================
|
||||
|
||||
To use Distribute in your project, the recommended way is to ship
|
||||
`distribute_setup.py` alongside your `setup.py` script and call
|
||||
it at the very begining of `setup.py` like this::
|
||||
|
||||
from distribute_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
Another way is to add ``Distribute`` in the ``install_requires`` option::
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(...
|
||||
install_requires=['distribute']
|
||||
)
|
||||
|
||||
|
||||
XXX to be finished
|
||||
Vendored
-170
@@ -1,170 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Script to fully automate the release process. Requires Python 2.6+
|
||||
with sphinx installed and the 'hg' command on the path.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import subprocess
|
||||
import shutil
|
||||
import os
|
||||
import sys
|
||||
import urllib2
|
||||
import getpass
|
||||
import collections
|
||||
|
||||
try:
|
||||
import keyring
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
VERSION = '0.6.34'
|
||||
|
||||
def get_next_version():
|
||||
digits = map(int, VERSION.split('.'))
|
||||
digits[-1] += 1
|
||||
return '.'.join(map(str, digits))
|
||||
|
||||
NEXT_VERSION = get_next_version()
|
||||
|
||||
files_with_versions = ('docs/conf.py', 'setup.py', 'release.py',
|
||||
'README.txt', 'distribute_setup.py')
|
||||
|
||||
def get_repo_name():
|
||||
"""
|
||||
Get the repo name from the hgrc default path.
|
||||
"""
|
||||
default = subprocess.check_output('hg paths default').strip()
|
||||
parts = default.split('/')
|
||||
if parts[-1] == '':
|
||||
parts.pop()
|
||||
return '/'.join(parts[-2:])
|
||||
|
||||
def get_mercurial_creds(system='https://bitbucket.org', username=None):
|
||||
"""
|
||||
Return named tuple of username,password in much the same way that
|
||||
Mercurial would (from the keyring).
|
||||
"""
|
||||
# todo: consider getting this from .hgrc
|
||||
username = username or getpass.getuser()
|
||||
keyring_username = '@@'.join((username, system))
|
||||
system = '@'.join((keyring_username, 'Mercurial'))
|
||||
password = (
|
||||
keyring.get_password(system, keyring_username)
|
||||
if 'keyring' in globals()
|
||||
else None
|
||||
)
|
||||
if not password:
|
||||
password = getpass.getpass()
|
||||
Credential = collections.namedtuple('Credential', 'username password')
|
||||
return Credential(username, password)
|
||||
|
||||
def add_milestone_and_version(version=NEXT_VERSION):
|
||||
auth = 'Basic ' + ':'.join(get_mercurial_creds()).encode('base64').strip()
|
||||
headers = {
|
||||
'Authorization': auth,
|
||||
}
|
||||
base = 'https://api.bitbucket.org'
|
||||
for type in 'milestones', 'versions':
|
||||
url = (base + '/1.0/repositories/{repo}/issues/{type}'
|
||||
.format(repo = get_repo_name(), type=type))
|
||||
req = urllib2.Request(url = url, headers = headers,
|
||||
data='name='+version)
|
||||
try:
|
||||
urllib2.urlopen(req)
|
||||
except urllib2.HTTPError as e:
|
||||
print(e.fp.read())
|
||||
|
||||
def bump_versions():
|
||||
list(map(bump_version, files_with_versions))
|
||||
|
||||
def bump_version(filename):
|
||||
with open(filename, 'rb') as f:
|
||||
lines = [line.replace(VERSION, NEXT_VERSION) for line in f]
|
||||
with open(filename, 'wb') as f:
|
||||
f.writelines(lines)
|
||||
|
||||
def do_release():
|
||||
assert all(map(os.path.exists, files_with_versions)), (
|
||||
"Expected file(s) missing")
|
||||
|
||||
assert has_sphinx(), "You must have Sphinx installed to release"
|
||||
|
||||
res = raw_input('Have you read through the SCM changelog and '
|
||||
'confirmed the changelog is current for releasing {VERSION}? '
|
||||
.format(**globals()))
|
||||
if not res.lower().startswith('y'):
|
||||
print("Please do that")
|
||||
raise SystemExit(1)
|
||||
|
||||
print("Travis-CI tests: http://travis-ci.org/#!/jaraco/distribute")
|
||||
res = raw_input('Have you or has someone verified that the tests '
|
||||
'pass on this revision? ')
|
||||
if not res.lower().startswith('y'):
|
||||
print("Please do that")
|
||||
raise SystemExit(2)
|
||||
|
||||
subprocess.check_call(['hg', 'tag', VERSION])
|
||||
|
||||
subprocess.check_call(['hg', 'update', VERSION])
|
||||
|
||||
has_docs = build_docs()
|
||||
if os.path.isdir('./dist'):
|
||||
shutil.rmtree('./dist')
|
||||
cmd = [sys.executable, 'setup.py', '-q', 'egg_info', '-RD', '-b', '',
|
||||
'sdist', 'register', 'upload']
|
||||
if has_docs:
|
||||
cmd.append('upload_docs')
|
||||
subprocess.check_call(cmd)
|
||||
upload_bootstrap_script()
|
||||
|
||||
# update to the tip for the next operation
|
||||
subprocess.check_call(['hg', 'update'])
|
||||
|
||||
# we just tagged the current version, bump for the next release.
|
||||
bump_versions()
|
||||
subprocess.check_call(['hg', 'ci', '-m',
|
||||
'Bumped to {NEXT_VERSION} in preparation for next '
|
||||
'release.'.format(**globals())])
|
||||
|
||||
# push the changes
|
||||
subprocess.check_call(['hg', 'push'])
|
||||
|
||||
add_milestone_and_version()
|
||||
|
||||
def has_sphinx():
|
||||
try:
|
||||
devnull = open(os.path.devnull, 'wb')
|
||||
subprocess.Popen(['sphinx-build', '--version'], stdout=devnull,
|
||||
stderr=subprocess.STDOUT).wait()
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def build_docs():
|
||||
if not os.path.isdir('docs'):
|
||||
return
|
||||
if os.path.isdir('docs/build'):
|
||||
shutil.rmtree('docs/build')
|
||||
subprocess.check_call([
|
||||
'sphinx-build',
|
||||
'-b', 'html',
|
||||
'-d', 'build/doctrees',
|
||||
'.',
|
||||
'build/html',
|
||||
],
|
||||
cwd='docs')
|
||||
return True
|
||||
|
||||
def upload_bootstrap_script():
|
||||
scp_command = 'pscp' if sys.platform.startswith('win') else 'scp'
|
||||
try:
|
||||
subprocess.check_call([scp_command, 'distribute_setup.py',
|
||||
'pypi@ziade.org:python-distribute.org/'])
|
||||
except:
|
||||
print("Unable to upload bootstrap script. Ask Tarek to do it.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
do_release()
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,41 +0,0 @@
|
||||
from distutils.command.bdist_wininst import bdist_wininst as _bdist_wininst
|
||||
import os, sys
|
||||
|
||||
class bdist_wininst(_bdist_wininst):
|
||||
|
||||
def create_exe(self, arcname, fullname, bitmap=None):
|
||||
_bdist_wininst.create_exe(self, arcname, fullname, bitmap)
|
||||
dist_files = getattr(self.distribution, 'dist_files', [])
|
||||
|
||||
if self.target_version:
|
||||
installer_name = os.path.join(self.dist_dir,
|
||||
"%s.win32-py%s.exe" %
|
||||
(fullname, self.target_version))
|
||||
pyversion = self.target_version
|
||||
|
||||
# fix 2.5 bdist_wininst ignoring --target-version spec
|
||||
bad = ('bdist_wininst','any',installer_name)
|
||||
if bad in dist_files:
|
||||
dist_files.remove(bad)
|
||||
else:
|
||||
installer_name = os.path.join(self.dist_dir,
|
||||
"%s.win32.exe" % fullname)
|
||||
pyversion = 'any'
|
||||
good = ('bdist_wininst', pyversion, installer_name)
|
||||
if good not in dist_files:
|
||||
dist_files.append(good)
|
||||
|
||||
def reinitialize_command (self, command, reinit_subcommands=0):
|
||||
cmd = self.distribution.reinitialize_command(
|
||||
command, reinit_subcommands)
|
||||
if command in ('install', 'install_lib'):
|
||||
cmd.install_lib = None # work around distutils bug
|
||||
return cmd
|
||||
|
||||
def run(self):
|
||||
self._is_running = True
|
||||
try:
|
||||
_bdist_wininst.run(self)
|
||||
finally:
|
||||
self._is_running = False
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
"""distutils.command.upload
|
||||
|
||||
Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
|
||||
|
||||
from distutils.errors import *
|
||||
from distutils.core import Command
|
||||
from distutils.spawn import spawn
|
||||
from distutils import log
|
||||
try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
import os
|
||||
import socket
|
||||
import platform
|
||||
import ConfigParser
|
||||
import httplib
|
||||
import base64
|
||||
import urlparse
|
||||
import cStringIO as StringIO
|
||||
|
||||
class upload(Command):
|
||||
|
||||
description = "upload binary package to PyPI"
|
||||
|
||||
DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
|
||||
|
||||
user_options = [
|
||||
('repository=', 'r',
|
||||
"url of repository [default: %s]" % DEFAULT_REPOSITORY),
|
||||
('show-response', None,
|
||||
'display full response text from server'),
|
||||
('sign', 's',
|
||||
'sign files to upload using gpg'),
|
||||
('identity=', 'i', 'GPG identity used to sign files'),
|
||||
]
|
||||
boolean_options = ['show-response', 'sign']
|
||||
|
||||
def initialize_options(self):
|
||||
self.username = ''
|
||||
self.password = ''
|
||||
self.repository = ''
|
||||
self.show_response = 0
|
||||
self.sign = False
|
||||
self.identity = None
|
||||
|
||||
def finalize_options(self):
|
||||
if self.identity and not self.sign:
|
||||
raise DistutilsOptionError(
|
||||
"Must use --sign for --identity to have meaning"
|
||||
)
|
||||
if os.environ.has_key('HOME'):
|
||||
rc = os.path.join(os.environ['HOME'], '.pypirc')
|
||||
if os.path.exists(rc):
|
||||
self.announce('Using PyPI login from %s' % rc)
|
||||
config = ConfigParser.ConfigParser({
|
||||
'username':'',
|
||||
'password':'',
|
||||
'repository':''})
|
||||
config.read(rc)
|
||||
if not self.repository:
|
||||
self.repository = config.get('server-login', 'repository')
|
||||
if not self.username:
|
||||
self.username = config.get('server-login', 'username')
|
||||
if not self.password:
|
||||
self.password = config.get('server-login', 'password')
|
||||
if not self.repository:
|
||||
self.repository = self.DEFAULT_REPOSITORY
|
||||
|
||||
def run(self):
|
||||
if not self.distribution.dist_files:
|
||||
raise DistutilsOptionError("No dist file created in earlier command")
|
||||
for command, pyversion, filename in self.distribution.dist_files:
|
||||
self.upload_file(command, pyversion, filename)
|
||||
|
||||
def upload_file(self, command, pyversion, filename):
|
||||
# Sign if requested
|
||||
if self.sign:
|
||||
gpg_args = ["gpg", "--detach-sign", "-a", filename]
|
||||
if self.identity:
|
||||
gpg_args[2:2] = ["--local-user", self.identity]
|
||||
spawn(gpg_args,
|
||||
dry_run=self.dry_run)
|
||||
|
||||
# Fill in the data
|
||||
f = open(filename,'rb')
|
||||
content = f.read()
|
||||
f.close()
|
||||
basename = os.path.basename(filename)
|
||||
comment = ''
|
||||
if command=='bdist_egg' and self.distribution.has_ext_modules():
|
||||
comment = "built on %s" % platform.platform(terse=1)
|
||||
data = {
|
||||
':action':'file_upload',
|
||||
'protocol_version':'1',
|
||||
'name':self.distribution.get_name(),
|
||||
'version':self.distribution.get_version(),
|
||||
'content':(basename,content),
|
||||
'filetype':command,
|
||||
'pyversion':pyversion,
|
||||
'md5_digest':md5(content).hexdigest(),
|
||||
}
|
||||
if command == 'bdist_rpm':
|
||||
dist, version, id = platform.dist()
|
||||
if dist:
|
||||
comment = 'built for %s %s' % (dist, version)
|
||||
elif command == 'bdist_dumb':
|
||||
comment = 'built for %s' % platform.platform(terse=1)
|
||||
data['comment'] = comment
|
||||
|
||||
if self.sign:
|
||||
asc_file = open(filename + ".asc")
|
||||
data['gpg_signature'] = (os.path.basename(filename) + ".asc", asc_file.read())
|
||||
asc_file.close()
|
||||
|
||||
# set up the authentication
|
||||
auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip()
|
||||
|
||||
# Build up the MIME payload for the POST data
|
||||
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
|
||||
sep_boundary = '\n--' + boundary
|
||||
end_boundary = sep_boundary + '--'
|
||||
body = StringIO.StringIO()
|
||||
for key, value in data.items():
|
||||
# handle multiple entries for the same name
|
||||
if type(value) != type([]):
|
||||
value = [value]
|
||||
for value in value:
|
||||
if type(value) is tuple:
|
||||
fn = ';filename="%s"' % value[0]
|
||||
value = value[1]
|
||||
else:
|
||||
fn = ""
|
||||
value = str(value)
|
||||
body.write(sep_boundary)
|
||||
body.write('\nContent-Disposition: form-data; name="%s"'%key)
|
||||
body.write(fn)
|
||||
body.write("\n\n")
|
||||
body.write(value)
|
||||
if value and value[-1] == '\r':
|
||||
body.write('\n') # write an extra newline (lurve Macs)
|
||||
body.write(end_boundary)
|
||||
body.write("\n")
|
||||
body = body.getvalue()
|
||||
|
||||
self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
|
||||
|
||||
# build the Request
|
||||
# We can't use urllib2 since we need to send the Basic
|
||||
# auth right with the first request
|
||||
schema, netloc, url, params, query, fragments = \
|
||||
urlparse.urlparse(self.repository)
|
||||
assert not params and not query and not fragments
|
||||
if schema == 'http':
|
||||
http = httplib.HTTPConnection(netloc)
|
||||
elif schema == 'https':
|
||||
http = httplib.HTTPSConnection(netloc)
|
||||
else:
|
||||
raise AssertionError, "unsupported schema "+schema
|
||||
|
||||
data = ''
|
||||
loglevel = log.INFO
|
||||
try:
|
||||
http.connect()
|
||||
http.putrequest("POST", url)
|
||||
http.putheader('Content-type',
|
||||
'multipart/form-data; boundary=%s'%boundary)
|
||||
http.putheader('Content-length', str(len(body)))
|
||||
http.putheader('Authorization', auth)
|
||||
http.endheaders()
|
||||
http.send(body)
|
||||
except socket.error, e:
|
||||
self.announce(str(e), log.ERROR)
|
||||
return
|
||||
|
||||
r = http.getresponse()
|
||||
if r.status == 200:
|
||||
self.announce('Server response (%s): %s' % (r.status, r.reason),
|
||||
log.INFO)
|
||||
else:
|
||||
self.announce('Upload failed (%s): %s' % (r.status, r.reason),
|
||||
log.ERROR)
|
||||
if self.show_response:
|
||||
print '-'*75, r.read(), '-'*75
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r
|
||||
__requires__ = """%(spec)r"""
|
||||
from pkg_resources import require; require("""%(spec)r""")
|
||||
del require
|
||||
__file__ = """%(dev_path)r"""
|
||||
execfile(__file__)
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
import urllib2
|
||||
import sys
|
||||
import os
|
||||
|
||||
if os.path.exists('distribute_setup.py'):
|
||||
print 'distribute_setup.py exists in the current dir, aborting'
|
||||
sys.exit(2)
|
||||
|
||||
print '**** Starting Test'
|
||||
print '\n\n'
|
||||
|
||||
is_jython = sys.platform.startswith('java')
|
||||
if is_jython:
|
||||
import subprocess
|
||||
|
||||
print 'Downloading bootstrap'
|
||||
file = urllib2.urlopen('http://nightly.ziade.org/distribute_setup.py')
|
||||
f = open('distribute_setup.py', 'w')
|
||||
f.write(file.read())
|
||||
f.close()
|
||||
|
||||
# running it
|
||||
args = [sys.executable] + ['distribute_setup.py']
|
||||
if is_jython:
|
||||
res = subprocess.call(args)
|
||||
else:
|
||||
res = os.spawnv(os.P_WAIT, sys.executable, args)
|
||||
|
||||
if res != 0:
|
||||
print '**** Test failed, please send me the output at tarek@ziade.org'
|
||||
os.remove('distribute_setup.py')
|
||||
sys.exit(2)
|
||||
|
||||
# now checking if Distribute is installed
|
||||
script = """\
|
||||
import sys
|
||||
try:
|
||||
import setuptools
|
||||
except ImportError:
|
||||
sys.exit(0)
|
||||
|
||||
sys.exit(hasattr(setuptools, "_distribute"))
|
||||
"""
|
||||
|
||||
root = 'script'
|
||||
seed = 0
|
||||
script_name = '%s%d.py' % (root, seed)
|
||||
|
||||
while os.path.exists(script_name):
|
||||
seed += 1
|
||||
script_name = '%s%d.py' % (root, seed)
|
||||
|
||||
f = open(script_name, 'w')
|
||||
try:
|
||||
f.write(script)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
try:
|
||||
args = [sys.executable] + [script_name]
|
||||
if is_jython:
|
||||
res = subprocess.call(args)
|
||||
else:
|
||||
res = os.spawnv(os.P_WAIT, sys.executable, args)
|
||||
|
||||
print '\n\n'
|
||||
if res:
|
||||
print '**** Test is OK'
|
||||
else:
|
||||
print '**** Test failed, please send me the output at tarek@ziade.org'
|
||||
finally:
|
||||
if os.path.exists(script_name):
|
||||
os.remove(script_name)
|
||||
os.remove('distribute_setup.py')
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
MANIFEST
|
||||
tests/test-scratch/*
|
||||
tests/test-cache/*
|
||||
tests/packages/FSPkg/FSPkg.egg-info
|
||||
testenv
|
||||
pip.egg-info/*
|
||||
ScriptTest-*.egg
|
||||
virtualenv-*.egg
|
||||
nose-*.egg/*
|
||||
wsgi_intercept-*.egg/*
|
||||
WSGIProxy-*.egg/*
|
||||
WebOb-*.egg
|
||||
Paste-*.egg/*
|
||||
mock-*egg
|
||||
tests/tests_cache/*
|
||||
dist/*
|
||||
docs/_build/*
|
||||
build/*
|
||||
*.pyc
|
||||
*.pyo
|
||||
pip-log.txt
|
||||
pip.log
|
||||
*.~
|
||||
Vendored
-48
@@ -1,48 +0,0 @@
|
||||
Alex Grönholm
|
||||
Alex Morega
|
||||
Alexandre Conrad
|
||||
Antti Kaihola
|
||||
Armin Ronacher
|
||||
Brian Rosner
|
||||
Carl Meyer
|
||||
Christian Oudard
|
||||
Cody Soyland
|
||||
Daniel Holth
|
||||
Dave Abrahams
|
||||
Francesco
|
||||
Hugo Lopes Tavares
|
||||
Ian Bicking
|
||||
Igor Sobreira
|
||||
Ionel Maries Cristian
|
||||
Jakub Vysoky
|
||||
Jannis Leidel
|
||||
Jay Graves
|
||||
John-Scott Atlakson
|
||||
Jon Parise
|
||||
Josh Bronson
|
||||
Kelsey Hightower
|
||||
Kenneth Belitzky
|
||||
Kumar McMillan
|
||||
Luke Macken
|
||||
Masklinn
|
||||
Marc Abramowitz
|
||||
Marcus Smith
|
||||
Matt Maker
|
||||
Nowell Strite
|
||||
Oliver Tonnhofer
|
||||
Olivier Girardot
|
||||
Patrick Jenkins
|
||||
Paul Nasrat
|
||||
Paul Oswald
|
||||
Paul van der Linden
|
||||
Peter Waller
|
||||
Piet Delport
|
||||
Qiangning Hong
|
||||
Rene Dudfield
|
||||
Ronny Pfannschmidt
|
||||
Simon Cross
|
||||
Stavros Korokithakis
|
||||
Thomas Johansson
|
||||
Vinay Sajip
|
||||
Vitaly Babiy
|
||||
Wil Tan
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
include AUTHORS.txt
|
||||
include LICENSE.txt
|
||||
recursive-include docs *.txt
|
||||
recursive-include docs *.html
|
||||
recursive-exclude docs/_build *.txt
|
||||
prune docs/_build/_sources
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
from packager import generate_script
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
file_name = os.path.join(here, 'get-pip.py')
|
||||
|
||||
entry = """
|
||||
import sys
|
||||
try:
|
||||
import setuptools
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
raise SystemExit("An error occured while trying to run %s. Make sure "
|
||||
"you have setuptools or distribute installed." % __file__)
|
||||
import pip
|
||||
pip.bootstrap()
|
||||
"""
|
||||
|
||||
def main():
|
||||
sys.stdout.write("Creating pip bootstrapper...")
|
||||
script = generate_script(entry, ['pip'])
|
||||
f = open(file_name, 'w')
|
||||
try:
|
||||
f.write(script)
|
||||
finally:
|
||||
f.close()
|
||||
sys.stdout.write('done.\n')
|
||||
if hasattr(os, 'chmod'):
|
||||
oldmode = os.stat(file_name).st_mode & 07777
|
||||
newmode = (oldmode | 0555) & 07777
|
||||
os.chmod(file_name, newmode)
|
||||
sys.stdout.write('Made resulting file %s executable.\n\n' % file_name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
from packager import generate_script
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
file_name = os.path.join(here, 'run-pip.py')
|
||||
|
||||
entry = """
|
||||
import sys
|
||||
try:
|
||||
import setuptools
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
raise SystemExit("An error occured while trying to run %s. Make sure "
|
||||
"you have setuptools or distribute installed." % __file__)
|
||||
import pip
|
||||
pip.main()
|
||||
"""
|
||||
|
||||
def main():
|
||||
sys.stdout.write("Creating standalone pip...")
|
||||
script = generate_script(entry, ['pip'])
|
||||
f = open(file_name, 'w')
|
||||
try:
|
||||
f.write(script)
|
||||
finally:
|
||||
f.close()
|
||||
sys.stdout.write('done.\n')
|
||||
if hasattr(os, 'chmod'):
|
||||
oldmode = os.stat(file_name).st_mode & 07777
|
||||
newmode = (oldmode | 0555) & 07777
|
||||
os.chmod(file_name, newmode)
|
||||
sys.stdout.write('Made resulting file %s executable.\n\n' % file_name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Vendored
-1153
File diff suppressed because it is too large
Load Diff
-68
@@ -1,68 +0,0 @@
|
||||
# Port of Ronny Pfannschmidt's genscript package
|
||||
# https://bitbucket.org/RonnyPfannschmidt/genscript
|
||||
|
||||
import sys
|
||||
import pickle
|
||||
import zlib
|
||||
import base64
|
||||
import os
|
||||
import fnmatch
|
||||
|
||||
|
||||
def find_toplevel(name):
|
||||
for syspath in sys.path:
|
||||
lib = os.path.join(syspath, name)
|
||||
if os.path.isdir(lib):
|
||||
return lib
|
||||
mod = lib + '.py'
|
||||
if os.path.isfile(mod):
|
||||
return mod
|
||||
raise LookupError(name)
|
||||
|
||||
|
||||
def pkgname(toplevel, rootpath, path):
|
||||
parts = path.split(os.sep)[len(rootpath.split(os.sep)):]
|
||||
return '.'.join([toplevel] + [os.path.splitext(x)[0] for x in parts])
|
||||
|
||||
|
||||
def pkg_to_mapping(name):
|
||||
toplevel = find_toplevel(name)
|
||||
if os.path.isfile(toplevel):
|
||||
return {name: toplevel.read()}
|
||||
|
||||
name2src = {}
|
||||
for root, dirs, files in os.walk(toplevel):
|
||||
for pyfile in files:
|
||||
if fnmatch.fnmatch(pyfile, '*.py'):
|
||||
pkg = pkgname(name, toplevel, os.path.join(root, pyfile))
|
||||
f = open(os.path.join(root, pyfile))
|
||||
try:
|
||||
name2src[pkg] = f.read()
|
||||
finally:
|
||||
f.close()
|
||||
return name2src
|
||||
|
||||
|
||||
def compress_mapping(mapping):
|
||||
data = pickle.dumps(mapping, 2)
|
||||
data = zlib.compress(data, 9)
|
||||
data = base64.encodestring(data)
|
||||
data = data.decode('ascii')
|
||||
return data
|
||||
|
||||
|
||||
def compress_packages(names):
|
||||
mapping = {}
|
||||
for name in names:
|
||||
mapping.update(pkg_to_mapping(name))
|
||||
return compress_mapping(mapping)
|
||||
|
||||
|
||||
def generate_script(entry, packages):
|
||||
data = compress_packages(packages)
|
||||
tmpl = open(os.path.join(os.path.dirname(__file__), 'template.py'))
|
||||
exe = tmpl.read()
|
||||
tmpl.close()
|
||||
exe = exe.replace('@SOURCES@', data)
|
||||
exe = exe.replace('@ENTRY@', entry)
|
||||
return exe
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
sources = """
|
||||
@SOURCES@"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import zlib
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
|
||||
def unpack(sources):
|
||||
temp_dir = tempfile.mkdtemp('-scratchdir', 'unpacker-')
|
||||
for package, content in sources.items():
|
||||
filepath = package.split(".")
|
||||
dirpath = os.sep.join(filepath[:-1])
|
||||
packagedir = os.path.join(temp_dir, dirpath)
|
||||
if not os.path.isdir(packagedir):
|
||||
os.makedirs(packagedir)
|
||||
mod = open(os.path.join(packagedir, "%s.py" % filepath[-1]), 'wb')
|
||||
try:
|
||||
mod.write(content.encode("ascii"))
|
||||
finally:
|
||||
mod.close()
|
||||
return temp_dir
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if sys.version_info >= (3, 0):
|
||||
exec("def do_exec(co, loc): exec(co, loc)\n")
|
||||
import pickle
|
||||
sources = sources.encode("ascii") # ensure bytes
|
||||
sources = pickle.loads(zlib.decompress(base64.decodebytes(sources)))
|
||||
else:
|
||||
import cPickle as pickle
|
||||
exec("def do_exec(co, loc): exec co in loc\n")
|
||||
sources = pickle.loads(zlib.decompress(base64.decodestring(sources)))
|
||||
|
||||
try:
|
||||
temp_dir = unpack(sources)
|
||||
sys.path.insert(0, temp_dir)
|
||||
|
||||
entry = """@ENTRY@"""
|
||||
do_exec(entry, locals())
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
Vendored
-130
@@ -1,130 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-compressor.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-compressor.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/django-compressor"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-compressor"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
make -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 45 KiB |
@@ -1,237 +0,0 @@
|
||||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #111111;
|
||||
color: #555555;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 300px;
|
||||
}
|
||||
|
||||
hr{
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 1em 30px 30px 30px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #555;
|
||||
width: 100%;
|
||||
padding: 13px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #6BA81E;
|
||||
line-height: 36px;
|
||||
color: #ffffff;
|
||||
text-shadow: 0px 1px 0 #444444;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #E2F3CC;
|
||||
}
|
||||
|
||||
div.related .right {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5em;
|
||||
width: 300px
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper{
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #222222;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
text-shadow: 1px 1px 0 white
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #888888;
|
||||
padding: 5px 20px;
|
||||
margin: 0.5em 0px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 10px 10px 20px;
|
||||
padding: 0;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
color: #E32E00;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #cccccc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.1em;
|
||||
padding: 0.15em 0.3em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input[type=text]{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #005B81;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #E32E00;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
color: #212224;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 5px 0 5px 0px;
|
||||
text-shadow: 0px 1px 0 white;
|
||||
border-bottom: 1px solid #C8D5E3;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 150%; }
|
||||
div.body h3 { font-size: 120%; }
|
||||
div.body h4 { font-size: 110%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.8em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.highlight{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eeeeee;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffffcc;
|
||||
border: 1px solid #ffff66;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #fafafa;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #ff6666;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
background-color: #fafafa;
|
||||
color: #222222;
|
||||
line-height: 1.5em;
|
||||
font-size: 1.1em;
|
||||
margin: 1.5em 0 1.5em 0;
|
||||
-webkit-box-shadow: 0px 0px 4px #d8d8d8;
|
||||
-moz-box-shadow: 0px 0px 4px #d8d8d8;
|
||||
box-shadow: 0px 0px 4px #d8d8d8;
|
||||
}
|
||||
|
||||
tt {
|
||||
color: #222222;
|
||||
padding: 1px 2px;
|
||||
font-size: 1.2em;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#table-of-contents ul {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
.c { color: #999988; font-style: italic } /* Comment */
|
||||
.k { font-weight: bold } /* Keyword */
|
||||
.o { font-weight: bold } /* Operator */
|
||||
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
|
||||
.c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.ge { font-style: italic } /* Generic.Emph */
|
||||
.gr { color: #aa0000 } /* Generic.Error */
|
||||
.gh { color: #999999 } /* Generic.Heading */
|
||||
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.go { color: #111 } /* Generic.Output */
|
||||
.gp { color: #555555 } /* Generic.Prompt */
|
||||
.gs { font-weight: bold } /* Generic.Strong */
|
||||
.gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.kc { font-weight: bold } /* Keyword.Constant */
|
||||
.kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.m { color: #009999 } /* Literal.Number */
|
||||
.s { color: #bb8844 } /* Literal.String */
|
||||
.na { color: #008080 } /* Name.Attribute */
|
||||
.nb { color: #999999 } /* Name.Builtin */
|
||||
.nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.no { color: #ff99ff } /* Name.Constant */
|
||||
.ni { color: #800080 } /* Name.Entity */
|
||||
.ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.nn { color: #555555 } /* Name.Namespace */
|
||||
.nt { color: #000080 } /* Name.Tag */
|
||||
.nv { color: purple } /* Name.Variable */
|
||||
.ow { font-weight: bold } /* Operator.Word */
|
||||
.mf { color: #009999 } /* Literal.Number.Float */
|
||||
.mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.sb { color: #bb8844 } /* Literal.String.Backtick */
|
||||
.sc { color: #bb8844 } /* Literal.String.Char */
|
||||
.sd { color: #bb8844 } /* Literal.String.Doc */
|
||||
.s2 { color: #bb8844 } /* Literal.String.Double */
|
||||
.se { color: #bb8844 } /* Literal.String.Escape */
|
||||
.sh { color: #bb8844 } /* Literal.String.Heredoc */
|
||||
.si { color: #bb8844 } /* Literal.String.Interpol */
|
||||
.sx { color: #bb8844 } /* Literal.String.Other */
|
||||
.sr { color: #808000 } /* Literal.String.Regex */
|
||||
.s1 { color: #bb8844 } /* Literal.String.Single */
|
||||
.ss { color: #bb8844 } /* Literal.String.Symbol */
|
||||
.bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.vc { color: #ff99ff } /* Name.Variable.Class */
|
||||
.vg { color: #ff99ff } /* Name.Variable.Global */
|
||||
.vi { color: #ff99ff } /* Name.Variable.Instance */
|
||||
.il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
@@ -1,4 +0,0 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = nature.css
|
||||
pygments_style = tango
|
||||
-252
@@ -1,252 +0,0 @@
|
||||
==========================================
|
||||
Hudson CI server installation step by step
|
||||
==========================================
|
||||
|
||||
Why Hudson
|
||||
==========
|
||||
|
||||
One of the advantages of `Hudson <hudson-ci.org/>`_ over
|
||||
`Buildbot <http://buildbot.net/>`_, for instance, is that
|
||||
almost everything is done via its web interface. So anyone can
|
||||
manage the continuous integration server easily.
|
||||
Another advantage over the other alternatives is Hudson has many
|
||||
`available plugins <http://wiki.hudson-ci.org/display/HUDSON/Plugins>`_,
|
||||
so you don't need to write your own.
|
||||
|
||||
Hudson runs on Java, so the next step is to install Java and its dependencies.
|
||||
|
||||
|
||||
Java and its dependencies
|
||||
=========================
|
||||
|
||||
You can install all Java related packages this [not recommended] way::
|
||||
|
||||
$ [sudo] apt-get install ca-certificates-java daemon default-jre\
|
||||
> default-jre-headless gcj-4.4-base gcj-4.4-jre-headless gcj-4.4-jre-lib\
|
||||
> icedtea-6-jre-cacao java-common libaccess-bridge-java\
|
||||
> libaccess-bridge-java-jni libgcj-common libgcj10 libjline-java \
|
||||
> openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib\
|
||||
> rhino tzdata-java tzdata
|
||||
|
||||
|
||||
Or try installing with the information in the next section and
|
||||
if you have problems, run::
|
||||
|
||||
$ [sudo] apt-get install -f
|
||||
|
||||
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
The recommended installation from `Hudson site for Debian users
|
||||
<http://hudson-ci.org/debian/>`_ is installing through the `.deb` package.
|
||||
The advantages are: you can automatically upgrade hudson via apt and
|
||||
use the `service` or `/etc/init.d` resource to start the daemon on boot.
|
||||
|
||||
To install Hudson as they recommend, do the following:
|
||||
|
||||
* Add the key to your system::
|
||||
|
||||
$ wget -O /tmp/key http://hudson-ci.org/debian/hudson-ci.org.key
|
||||
$ [sudo] apt-key add /tmp/key
|
||||
|
||||
|
||||
* Then install Hudson::
|
||||
|
||||
$ wget -O /tmp/hudson.deb http://hudson-ci.org/latest/debian/hudson.deb
|
||||
$ [sudo] dpkg --install /tmp/hudson.deb
|
||||
|
||||
|
||||
When you reboot the computer the web daemon will be started at
|
||||
http://localhost:8080. If you don't want to reboot the computer, run::
|
||||
|
||||
$ [sudo] service hudson start
|
||||
or
|
||||
$ [sudo] /etc/init.d/hudson start
|
||||
|
||||
|
||||
|
||||
|
||||
Apache
|
||||
======
|
||||
|
||||
It is not necessary for all users, but if you want to set up apache to run
|
||||
the web interface, you should follow this tutorial:
|
||||
http://wiki.hudson-ci.org/display/HUDSON/Running+Hudson+behind+Apache
|
||||
|
||||
|
||||
Plugins
|
||||
=======
|
||||
|
||||
Installing plugins in Hudson is very easy.
|
||||
Just click *Manage Hudson*, then *Manage Plugins*.
|
||||
The tab *Updates* shows all available updates to installed plugins.
|
||||
But what we need now is to install plugins. So we must go to the
|
||||
*Available* tab and check what we want to be installed and then press the
|
||||
*Install* button in the end of the page.
|
||||
|
||||
The Hudson server hosted at http://ci.cloudsilverlining.org has the following
|
||||
plugins installed for pip project:
|
||||
|
||||
* Hudson IRC Plugin
|
||||
* Green Balls
|
||||
* Hudson Continuous Integration game
|
||||
* Hudson instant-messaging plugin
|
||||
* Hudson Jabber notifier plugin
|
||||
* Hudson Email Extension Plugin
|
||||
* Hudson Mercurial plugin
|
||||
|
||||
|
||||
Creating a Job
|
||||
==============
|
||||
|
||||
Before Creating a Job for pip
|
||||
-----------------------------
|
||||
|
||||
Hudson manages "jobs". Jobs are complete builds to Hudson. For instance,
|
||||
you want to build pip project and run its tests with nosetests.
|
||||
This section assumes you have all needed `dependencies installed`_.
|
||||
|
||||
You need to set up some configuration in Hudson before creating your first job.
|
||||
Go to Hudson home page, "Manage Hudson", then "Configure System".
|
||||
|
||||
In the Mercurial section, fill the "Add Mercurial" section with:
|
||||
|
||||
* Name: `hg`
|
||||
* Installation directory: `/usr`
|
||||
* Executable: `INSTALLATION/bin/hg`
|
||||
|
||||
In the Shell section fill the shell executable with `/bin/bash`.
|
||||
|
||||
Then press the "Save" button in the bottom of the page.
|
||||
|
||||
|
||||
|
||||
|
||||
Configuring a Job Step by Step
|
||||
------------------------------
|
||||
|
||||
* Go to the home of the Hudson web interface
|
||||
* Click *New Job*
|
||||
* Pick a name for the job - pip, for instance
|
||||
* Mark the option "Build a free-style software project"
|
||||
* Press "OK" button
|
||||
|
||||
Now you were redirected to the job's configuration page. Here you will
|
||||
tell Hudson how it will build your job. The most important
|
||||
steps are listed (assume Mercurial plugin is installed):
|
||||
|
||||
* Check "Mercurial" in Source Control Management section
|
||||
* Fill in the repository URL with **https://github.com/pypa/pip**
|
||||
* Mark "Build periodically" in *Build Triggers* section
|
||||
* Add "0 0 \* \* \*" (without quotes) to tell hudson you want to
|
||||
run your build everyday at midnight
|
||||
* Click "Add Build Step" in the *Build* section and pick "Execute Shell"
|
||||
|
||||
This box will contain all code you want your build run. To run pip's tests
|
||||
we need to install pip tests's depencies and run nosetests.
|
||||
Add the following lines to the box (it assumes you have virtualenv
|
||||
in your system's python)::
|
||||
|
||||
python -mvirtualenv --no-site-packages pip_virtualenv
|
||||
source pip_virtualenv/bin/activate
|
||||
cd $WORKSPACE/..
|
||||
easy_install -U pip
|
||||
cd $WORKSPACE
|
||||
pip install virtualenv scripttest nose
|
||||
nosetests tests -v
|
||||
|
||||
The *$WORKSPACE* environment variable is the current build workspace,
|
||||
in the case above it is the clone repository path. The `cd` stuff is
|
||||
a work around to a pip's bug.
|
||||
|
||||
The process execute above means:
|
||||
|
||||
* create a virtualenv called **pip_virtualenv** without shared site-packages
|
||||
* activate the environment
|
||||
* updates system's pip
|
||||
* install pip tests's dependencies
|
||||
* run nosetests in the current directory
|
||||
|
||||
|
||||
Press the "Save" button and in the next page test if the build is correct
|
||||
by clicking "Build now" button.
|
||||
|
||||
In the left sidebar will appear the run builds and the running (if exists).
|
||||
Click the top build, then "Console Output". Now you can
|
||||
watch what Hudson is doing to build your job and watch the results.
|
||||
|
||||
|
||||
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
If you change anything in your system environment, like updating
|
||||
your environment configuration files, and realize Hudson
|
||||
didn't catch your changes, try restarting it::
|
||||
|
||||
$ [sudo] service hudson stop
|
||||
$ [sudo] service hudson start
|
||||
|
||||
If when you run the `start` command you get an error telling you the port
|
||||
is being used, wait about 2 or 3 seconds and try the command again - it's the
|
||||
time the port releasing may take.
|
||||
|
||||
What is covered here is the basic knowledge to start setting up and using
|
||||
a Hudson server, the goal is not teaching all about Hudson or all about
|
||||
how to set up every detail.
|
||||
|
||||
There is a running Hudson server aimed for pip project here:
|
||||
http://ci.cloudsilverlining.org/view/pip
|
||||
|
||||
|
||||
Creating a Windows Slave to Run Jobs
|
||||
====================================
|
||||
|
||||
After starting Hudson on Linux, start your Windows machine and access the
|
||||
Hudson web interface.
|
||||
|
||||
Adding a Windows Node to Hudson CI Server
|
||||
-----------------------------------------
|
||||
|
||||
Click "Manage Hudson", "Manage Nodes", "New Node". The **Node name** value
|
||||
must be the Windows machine domain name - mywindowsslave.myhost.com, for
|
||||
instance.
|
||||
|
||||
The "Launch method" should be **Launch slave agents via JNLP**
|
||||
|
||||
.. image:: _static/launch-jnlp-slave.JPG
|
||||
:width: 500px
|
||||
:target: _static/launch-jnlp-slave.JPG
|
||||
|
||||
Then press the **Add** button, and in the next page click
|
||||
the **Launch** icon.
|
||||
|
||||
.. image:: _static/slave-launch-icon.png
|
||||
:width: 500px
|
||||
:target: _static/launch-jnlp-slave.JPG
|
||||
|
||||
Now you are able to create jobs tied to this Windows machine.
|
||||
|
||||
|
||||
Creating Tied Jobs
|
||||
------------------
|
||||
|
||||
The process of creating a job is almost the same as the list in the
|
||||
`Creating a Job`_ section, the only difference is that you need
|
||||
to mark the **Tie this project to a node** option and select what
|
||||
node you want to run that build.
|
||||
|
||||
There is a difference in build commands, relying on variables. On Linux
|
||||
they all start with `$`, like `$WORKSPACE`.
|
||||
In Windows they will be enclosed by `%`, like `%WORKSPACE%`. And everything
|
||||
you were doing depending on Bash, you will need to change to DOS
|
||||
prompt commands and batch files.
|
||||
|
||||
|
||||
|
||||
.. _dependencies installed: running-tests.html#system-requirements
|
||||
.. _creating a job: #creating-a-job
|
||||
Vendored
-195
@@ -1,195 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# pip documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Apr 22 22:08:49 2008
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.append(os.path.abspath('.'))
|
||||
#sys.path.append(os.path.join(os.path.dirname(__file__), '../'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
#extensions = ['sphinx.ext.autodoc']
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.txt'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'pip'
|
||||
copyright = '2008-2011, The pip developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
release = "1.1"
|
||||
version = '.'.join(release.split('.')[:2])
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of documents that shouldn't be included in the build.
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directory, that shouldn't be searched
|
||||
# for source files.
|
||||
exclude_trees = ['build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'nature'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = ['_theme']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = '_static/piplogo.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = 'favicon.png'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_use_modindex = False
|
||||
|
||||
# If false, no index is generated.
|
||||
html_use_index = False
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
html_show_sourcelink = False
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pipdocs'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'pip.tex', u'pip Documentation',
|
||||
u'The pip developers', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
Configuration
|
||||
=============
|
||||
|
||||
pip allows you to set its default options by using the following facilities,
|
||||
in the order of each item's importance:
|
||||
|
||||
1. Command line options
|
||||
|
||||
2. `Environment variables`_
|
||||
|
||||
3. `Config files`_
|
||||
|
||||
1. Command specific section, e.g. ``[install]``
|
||||
2. Global section ``[global]``
|
||||
|
||||
That means it will check each of those configuration sources and set the
|
||||
defaults appropriately.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
- ``--host=foo`` overrides ``PIP_HOST=foo``
|
||||
- ``PIP_HOST=foo`` overrides a config file with ``[global] host = foo``
|
||||
- A command specific section in the config file ``[<command>] host = bar``
|
||||
overrides the option with same name in the ``[global]`` config file section
|
||||
- Environment variables override config files
|
||||
|
||||
Config files
|
||||
------------
|
||||
|
||||
pip allows you to set all command line option defaults in a standard ini
|
||||
style config file.
|
||||
|
||||
The names of the settings are derived from the long command line option, e.g.
|
||||
if you want to use a different package index (``--index-url``) and set the
|
||||
HTTP timeout (``--default-timeout``) to 60 seconds your config file would
|
||||
look like this:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[global]
|
||||
timeout = 60
|
||||
index-url = http://download.zope.org/ppix
|
||||
|
||||
Each subcommand can be configured optionally in its own section so that every
|
||||
global setting with the same name will be overridden; e.g. decreasing the
|
||||
``timeout`` to ``10`` seconds when running the `freeze`
|
||||
(`Freezing Requirements <./#freezing-requirements>`_) command and using
|
||||
``60`` seconds for all other commands is possible with:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[global]
|
||||
timeout = 60
|
||||
|
||||
[freeze]
|
||||
timeout = 10
|
||||
|
||||
Boolean options like ``--ignore-installed`` or ``--no-dependencies`` can be
|
||||
set like this:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[install]
|
||||
ignore-installed = true
|
||||
no-dependencies = yes
|
||||
|
||||
Appending options like ``--find-links`` can be written on multiple lines:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[global]
|
||||
find-links =
|
||||
http://download.example.com
|
||||
|
||||
[install]
|
||||
find-links =
|
||||
http://mirror1.example.com
|
||||
http://mirror2.example.com
|
||||
|
||||
Location
|
||||
********
|
||||
|
||||
The names and locations of the configuration files vary slightly across
|
||||
platforms.
|
||||
|
||||
On Unix and Mac OS X the configuration file is: :file:`$HOME/.pip/pip.conf`
|
||||
|
||||
And on Windows, the configuration file is: :file:`%HOME%\\pip\\pip.ini`
|
||||
|
||||
Environment variables
|
||||
-----------------------
|
||||
|
||||
Just like with `config files`_, each of pip's command line options
|
||||
(long version, e.g. ``--find-links``) are automatically set by looking for
|
||||
environment variables with the name format ``PIP_<UPPER_NAME>``. That means
|
||||
the name of the command line options are capitalized and have dashes (``-``)
|
||||
replaced with underscores (``_``).
|
||||
|
||||
For example, to redefine the default timeout you can also set an
|
||||
environment variable::
|
||||
|
||||
export PIP_DEFAULT_TIMEOUT=60
|
||||
pip install ipython
|
||||
|
||||
Which is the same as passing the option to pip directly::
|
||||
|
||||
pip --default-timeout=60 install ipython
|
||||
|
||||
This also works for appending command line options, like ``--find-links``.
|
||||
Just leave an empty space between the passsed values, e.g.::
|
||||
|
||||
export PIP_FIND_LINKS="http://mirror1.example.com http://mirror2.example.com"
|
||||
|
||||
is the same as calling::
|
||||
|
||||
pip install --find-links=http://mirror1.example.com --find-links=http://mirror2.example.com
|
||||
|
||||
Configuration options
|
||||
---------------------
|
||||
|
||||
Mirror support
|
||||
**************
|
||||
|
||||
The `PyPI mirroring infrastructure <http://pypi.python.org/mirrors>`_ as
|
||||
described in `PEP 381 <http://www.python.org/dev/peps/pep-0381/>`_ can be
|
||||
used by passing the ``--use-mirrors`` option to the install command.
|
||||
Alternatively, you can use the other ways to configure pip, e.g.::
|
||||
|
||||
$ export PIP_USE_MIRRORS=true
|
||||
|
||||
If enabled, pip will automatically query the DNS entry of the mirror index URL
|
||||
to find the list of mirrors to use. In case you want to override this list,
|
||||
please use the ``--mirrors`` option of the install command, or add to your pip
|
||||
configuration file::
|
||||
|
||||
[install]
|
||||
use-mirrors = true
|
||||
mirrors =
|
||||
http://d.pypi.python.org
|
||||
http://b.pypi.python.org
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
=================
|
||||
How to contribute
|
||||
=================
|
||||
|
||||
|
||||
All kinds of contributions are welcome - code, tests, documentation,
|
||||
bug reports, ideas, etc.
|
||||
|
||||
|
||||
Release Schedule
|
||||
================
|
||||
|
||||
Minor releases of pip (e.g. 1.1, 1.2, 1.3...) occur every four months
|
||||
(beginning with the release of pip 1.0 on April 4, 2011). Two weeks before a
|
||||
scheduled release, a new branch ``release/X.Y`` is created for release testing
|
||||
and preparation. This branch is only open to bugfixes.
|
||||
|
||||
.. _contributing-with-code:
|
||||
|
||||
Contributing with Code
|
||||
======================
|
||||
|
||||
Forking through Github
|
||||
----------------------
|
||||
|
||||
First of all, you need to fork the the official repository, which is
|
||||
https://github.com/pypa/pip.
|
||||
|
||||
Log in to Github, go to the `pip repository page
|
||||
<https://github.com/pypa/pip>`_, follow the **fork** link, wait for Github
|
||||
to copy the repository and then clone your fork, like::
|
||||
|
||||
$ git clone https://github.com/YOU_USER_NAME/pip
|
||||
|
||||
Now you can change whatever you want, commit, push to your fork and when your
|
||||
contribution is done, follow the **pull request** link and send us a request
|
||||
explaining what you did and why.
|
||||
|
||||
Branches
|
||||
--------
|
||||
|
||||
Pip uses the `git-flow`_ branching model. The default branch on GitHub is
|
||||
``develop``, and all development work (new features and bugfixes) should happen
|
||||
in that branch. The ``master`` branch is stable, and reflects the last released
|
||||
state.
|
||||
|
||||
.. _git-flow: http://nvie.com/posts/a-successful-git-branching-model/
|
||||
|
||||
All tests should pass
|
||||
---------------------
|
||||
|
||||
Almost all changes to pip should be accompanied by automated tests -
|
||||
especially ones adding new behavior.
|
||||
|
||||
`Nose`_ is used to find and run all tests. Take a look at :doc:`running-tests`
|
||||
to see what you need and how you should run the tests.
|
||||
|
||||
Before sending us a pull request, please, be sure all tests pass.
|
||||
|
||||
Supported Python versions
|
||||
-------------------------
|
||||
|
||||
Pip supports Python versions 2.4, 2.5, 2.6, 2.7, 3.1, and 3.2, from a single
|
||||
codebase (without use of 2to3 translation). Untested contributions frequently
|
||||
break Python 2.4 or 3.x compatibility. Please run the tests on at least 2.4 and
|
||||
3.2 and report your results when sending a pull request.
|
||||
|
||||
Continuous Integration server
|
||||
-----------------------------
|
||||
|
||||
We have a continuous integration server running all pip related tests at
|
||||
http://ci.cloudsilverlining.org/view/pip. But if you want to have your own,
|
||||
you can learn how to set up a Hudson CI server like that in the
|
||||
:doc:`ci-server-step-by-step` page.
|
||||
|
||||
|
||||
|
||||
Running the Tests
|
||||
=================
|
||||
|
||||
Pip uses some system tools - VCS related tools - in its tests, so you need to
|
||||
intall them (Linux)::
|
||||
|
||||
sudo apt-get install subversion bzr git-core mercurial
|
||||
|
||||
Or downloading and installing `Subversion
|
||||
<http://subversion.apache.org/packages.html>`_, `Bazaar
|
||||
<http://wiki.bazaar.canonical.com/Download>`_, `Git
|
||||
<http://git-scm.com/download>`_ and `Mercurial
|
||||
<http://mercurial.selenic.com/downloads/>`_ manually.
|
||||
|
||||
|
||||
After all requirements (system and python) are installed,
|
||||
just run the following command::
|
||||
|
||||
$ python setup.py test
|
||||
|
||||
Running tests directly with Nose
|
||||
--------------------------------
|
||||
|
||||
If you want to run only a selection of the tests, you'll need to run them
|
||||
directly with nose instead. Create a virtualenv, and install required
|
||||
packages::
|
||||
|
||||
pip install nose virtualenv scripttest mock
|
||||
|
||||
Run nosetests::
|
||||
|
||||
nosetests
|
||||
|
||||
Or select just a single test to run::
|
||||
|
||||
cd tests; nosetests test_upgrade.py:test_uninstall_rollback
|
||||
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
Locale Warnings
|
||||
There was a problem with locales configuration when running tests in a Hudson
|
||||
CI Server that broke some tests. The problem was not with pip, but with
|
||||
`locales` configuration. Hudson was not setting LANG environment variable
|
||||
correctly, so the solution to fix it was changing default language to
|
||||
en_US.UTF-8.
|
||||
The following has been done in a Ubuntu Server 9.10 machine::
|
||||
|
||||
$ sudo locale-gen en_US en_US.UTF-8
|
||||
$ sudo dpkg-reconfigure locales
|
||||
$ sudo update-locale LANG=en_US.UTF-8
|
||||
|
||||
|
||||
|
||||
Contributing with Tests
|
||||
=======================
|
||||
|
||||
Pip's test coverage is not as good as we would like, so contributions of
|
||||
additional tests are welcome. You can contribute these the same way you would
|
||||
contribute any other kind of code: see the :ref:`contributing-with-code`
|
||||
section.
|
||||
|
||||
|
||||
Contributing with Bug Reports
|
||||
=============================
|
||||
|
||||
Pip project is hosted at `Github`_ and uses its issue tracker system.
|
||||
|
||||
If you have found a bug and want to report it, go to `pip issue tracker page`_,
|
||||
click **Create new**, add a descriptive
|
||||
title (so we can easily identify what the bug is) and fill the description box
|
||||
explaining how you got the bug, what pip version you were using and what is
|
||||
your operating system, so we can reproduce the bug to try fixing it.
|
||||
|
||||
|
||||
|
||||
Contributing with Ideas
|
||||
=======================
|
||||
|
||||
We are always open to new ideas, and we will enjoy yours. You can send
|
||||
enhancement ideas and proposals via `pip issue tracker page`_,
|
||||
`virtualenv mailing list`_, or #pip channel at freenode.
|
||||
|
||||
|
||||
|
||||
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.3/
|
||||
.. _Github: http://github.com/
|
||||
.. _pip issue tracker page: https://github.com/pypa/pip/issues
|
||||
.. _virtualenv mailing list: http://groups.google.com/group/python-virtualenv/
|
||||
Vendored
-12
@@ -1,12 +0,0 @@
|
||||
========
|
||||
Glossary
|
||||
========
|
||||
|
||||
.. glossary::
|
||||
|
||||
PyPI
|
||||
The `Python Package Index`_, formerly known as the Cheese Shop,
|
||||
is a central catalog of Python packages. By default, when
|
||||
installing packages,`pip` searches for them in PyPI.
|
||||
|
||||
.. _`Python Package Index`: http://pypi.python.org/pypi
|
||||
Vendored
-54
@@ -1,54 +0,0 @@
|
||||
pip
|
||||
===
|
||||
|
||||
`pip` is a tool for installing and managing Python packages, such as
|
||||
those found in the `Python Package Index`_. It's a replacement for
|
||||
easy_install_.
|
||||
::
|
||||
|
||||
$ pip install simplejson
|
||||
[... progress report ...]
|
||||
Successfully installed simplejson
|
||||
|
||||
.. _`Python Package Index`: http://pypi.python.org/pypi
|
||||
.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
|
||||
|
||||
Upgrading a package::
|
||||
|
||||
$ pip install --upgrade simplejson
|
||||
[... progress report ...]
|
||||
Successfully installed simplejson
|
||||
|
||||
Removing a package::
|
||||
|
||||
$ pip uninstall simplejson
|
||||
Uninstalling simplejson:
|
||||
/home/me/env/lib/python2.7/site-packages/simplejson
|
||||
/home/me/env/lib/python2.7/site-packages/simplejson-2.2.1-py2.7.egg-info
|
||||
Proceed (y/n)? y
|
||||
Successfully uninstalled simplejson
|
||||
|
||||
.. comment: split here
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installing
|
||||
usage
|
||||
requirements
|
||||
configuration
|
||||
other-tools
|
||||
contributing
|
||||
news
|
||||
glossary
|
||||
|
||||
.. comment: split here
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
The homepage for pip is at `pip-installer.org <http://www.pip-installer.org/>`_.
|
||||
Bugs can be filed in the `pip issue tracker
|
||||
<https://github.com/pypa/pip/issues/>`_. Discussion happens on the
|
||||
`virtualenv email group
|
||||
<http://groups.google.com/group/python-virtualenv?hl=en>`_.
|
||||
Vendored
-66
@@ -1,66 +0,0 @@
|
||||
Installation instructions
|
||||
=========================
|
||||
|
||||
The recommended way to use pip is within `virtualenv
|
||||
<http://www.virtualenv.org>`_, since every virtualenv has pip installed in it
|
||||
automatically. This does not require root access or modify your system Python
|
||||
installation. For instance::
|
||||
|
||||
$ curl -O https://raw.github.com/pypa/virtualenv/master/virtualenv.py
|
||||
$ python virtualenv.py my_new_env
|
||||
$ . my_new_env/bin/activate
|
||||
(my_new_env)$ pip install ...
|
||||
|
||||
When used in this manner, pip will only affect the active virtual environment.
|
||||
If you do want to install pip globally into your Python installation, see the
|
||||
instructions below.
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Prior to installing pip make sure you have either `setuptools
|
||||
<http://pypi.python.org/pypi/setuptools>`_ or `distribute
|
||||
<http://pypi.python.org/pypi/distribute>`_ installed. Please consult your
|
||||
operating system's package manager or install it manually::
|
||||
|
||||
$ curl http://python-distribute.org/distribute_setup.py | python
|
||||
|
||||
.. warning::
|
||||
|
||||
If you are using Python 3.X you **must** use distribute; setuptools doesn't
|
||||
support Python 3.X.
|
||||
|
||||
Using the installer
|
||||
-------------------
|
||||
|
||||
Download `get-pip.py <https://raw.github.com/pypa/pip/master/contrib/get-pip.py>`_
|
||||
and execute it, using the Python interpreter of your choice::
|
||||
|
||||
$ curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
|
||||
|
||||
This may have to be run as root.
|
||||
|
||||
Alternative installation procedures
|
||||
-----------------------------------
|
||||
|
||||
Using the source distribution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can find the source on `PyPI <http://pypi.python.org/pypi/pip>`_::
|
||||
|
||||
$ curl -O http://pypi.python.org/packages/source/p/pip/pip-1.0.tar.gz
|
||||
$ tar xvfz pip-1.0.tar.gz
|
||||
$ cd pip-1.0
|
||||
$ python setup.py install # may need to be root
|
||||
|
||||
Installing the development version
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
First you will need to clone the git repo::
|
||||
|
||||
$ git clone https://github.com/pypa/pip.git
|
||||
|
||||
Now we can install from the repo::
|
||||
|
||||
$ cd pip
|
||||
$ python setup.py install # may need to be root
|
||||
Vendored
-170
@@ -1,170 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-compressor.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-compressor.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
=============================
|
||||
Relationship with other tools
|
||||
=============================
|
||||
|
||||
Pip Compared To easy_install
|
||||
----------------------------
|
||||
|
||||
pip is meant to improve on easy_install. Some of the improvements:
|
||||
|
||||
* All packages are downloaded before installation. Partially-completed
|
||||
installation doesn't occur as a result.
|
||||
|
||||
* Care is taken to present useful output on the console.
|
||||
|
||||
* The reasons for actions are kept track of. For instance, if a package is
|
||||
being installed, pip keeps track of why that package was required.
|
||||
|
||||
* Error messages should be useful.
|
||||
|
||||
* The code is relatively concise and cohesive, making it easier to use
|
||||
programmatically.
|
||||
|
||||
* Packages don't have to be installed as egg archives, they can be installed
|
||||
flat (while keeping the egg metadata).
|
||||
|
||||
* Native support for other version control systems (Git, Mercurial and Bazaar)
|
||||
|
||||
* Uninstallation of packages.
|
||||
|
||||
* Simple to define fixed sets of requirements and reliably reproduce a
|
||||
set of packages.
|
||||
|
||||
pip doesn't do everything that easy_install does. Specifically:
|
||||
|
||||
* It cannot install from eggs. It only installs from source. (In the
|
||||
future it would be good if it could install binaries from Windows ``.exe``
|
||||
or ``.msi`` -- binary install on other platforms is not a priority.)
|
||||
|
||||
* It doesn't understand Setuptools extras (like ``package[test]``). This should
|
||||
be added eventually.
|
||||
|
||||
* It is incompatible with some packages that extensively customize distutils
|
||||
or setuptools in their ``setup.py`` files.
|
||||
|
||||
pip is complementary with `virtualenv
|
||||
<http://pypi.python.org/pypi/virtualenv>`__, and it is encouraged that you use
|
||||
virtualenv to isolate your installation.
|
||||
|
||||
Using pip with virtualenv
|
||||
-------------------------
|
||||
|
||||
pip is most nutritious when used with `virtualenv
|
||||
<http://pypi.python.org/pypi/virtualenv>`__. One of the reasons pip
|
||||
doesn't install "multi-version" eggs is that virtualenv removes much of the need
|
||||
for it. Because pip is installed by virtualenv, just use
|
||||
``path/to/my/environment/bin/pip`` to install things into that
|
||||
specific environment.
|
||||
|
||||
To tell pip to only run if there is a virtualenv currently activated,
|
||||
and to bail if not, use::
|
||||
|
||||
export PIP_REQUIRE_VIRTUALENV=true
|
||||
|
||||
|
||||
Using pip with virtualenvwrapper
|
||||
---------------------------------
|
||||
|
||||
If you are using `virtualenvwrapper
|
||||
<http://www.doughellmann.com/projects/virtualenvwrapper/>`_, you might
|
||||
want pip to automatically create its virtualenvs in your
|
||||
``$WORKON_HOME``.
|
||||
|
||||
You can tell pip to do so by defining ``PIP_VIRTUALENV_BASE`` in your
|
||||
environment and setting it to the same value as that of
|
||||
``$WORKON_HOME``.
|
||||
|
||||
Do so by adding the line::
|
||||
|
||||
export PIP_VIRTUALENV_BASE=$WORKON_HOME
|
||||
|
||||
in your .bashrc under the line starting with ``export WORKON_HOME``.
|
||||
|
||||
Using pip with buildout
|
||||
-----------------------
|
||||
|
||||
If you are using `zc.buildout
|
||||
<http://pypi.python.org/pypi/zc.buildout>`_ you should look at
|
||||
`gp.recipe.pip <http://pypi.python.org/pypi/gp.recipe.pip>`_ as an
|
||||
option to use pip and virtualenv in your buildouts.
|
||||
|
||||
Using pip with the "user scheme"
|
||||
--------------------------------
|
||||
|
||||
With Python 2.6 came the `"user scheme" for installation
|
||||
<http://docs.python.org/install/index.html#alternate-installation-the-user-scheme>`_, which means that all
|
||||
Python distributions support an alternative install location that is specific to a user.
|
||||
The default location for each OS is explained in the python documentation
|
||||
for the `site.USER_BASE <http://docs.python.org/library/site.html#site.USER_BASE>`_ variable.
|
||||
This mode of installation can be turned on by
|
||||
specifying the ``--user`` option to ``pip install``.
|
||||
|
||||
Moreover, the "user scheme" can be customized by setting the
|
||||
``PYTHONUSERBASE`` environment variable, which updates the value of ``site.USER_BASE``.
|
||||
|
||||
To install "somepackage" into an environment with site.USER_BASE customized to '/myappenv', do the following::
|
||||
|
||||
export PYTHONUSERBASE=/myappenv
|
||||
pip install --user somepackage
|
||||
|
||||
|
||||
Command line completion
|
||||
-----------------------
|
||||
|
||||
pip comes with support for command line completion in bash and zsh and
|
||||
allows you tab complete commands and options. To enable it you simply
|
||||
need copy the required shell script to the your shell startup file
|
||||
(e.g. ``.profile`` or ``.zprofile``) by running the special ``completion``
|
||||
command, e.g. for bash::
|
||||
|
||||
$ pip completion --bash >> ~/.profile
|
||||
|
||||
And for zsh::
|
||||
|
||||
$ pip completion --zsh >> ~/.zprofile
|
||||
|
||||
Alternatively, you can use the result of the ``completion`` command
|
||||
directly with the eval function of you shell, e.g. by adding::
|
||||
|
||||
eval "`pip completion --bash`"
|
||||
|
||||
to your startup file.
|
||||
-246
@@ -1,246 +0,0 @@
|
||||
.. _`requirements-files`:
|
||||
|
||||
==================
|
||||
Requirements files
|
||||
==================
|
||||
|
||||
When installing software, and Python packages in particular, it's common that
|
||||
you get a lot of libraries installed. You just did ``easy_install MyPackage``
|
||||
and you get a dozen packages. Each of these packages has its own version.
|
||||
|
||||
Maybe you ran that installation and it works. Great! Will it keep working?
|
||||
Did you have to provide special options to get it to find everything? Did you
|
||||
have to install a bunch of other optional pieces? Most of all, will you be able
|
||||
to do it again? Requirements files give you a way to create an *environment*:
|
||||
a *set* of packages that work together.
|
||||
|
||||
If you've ever tried to setup an application on a new system, or with slightly
|
||||
updated pieces, and had it fail, pip requirements are for you. If you
|
||||
haven't had this problem then you will eventually, so pip requirements are
|
||||
for you too -- requirements make explicit, repeatable installation of packages.
|
||||
|
||||
So what are requirements files? They are very simple: lists of packages to
|
||||
install. Instead of running something like ``pip install MyApp`` and
|
||||
getting whatever libraries come along, you can create a requirements file
|
||||
something like::
|
||||
|
||||
MyApp
|
||||
Framework==0.9.4
|
||||
Library>=0.2
|
||||
|
||||
If you save this in ``requirements.txt``, then you can ``pip install -r
|
||||
requirements.txt``. Regardless of what MyApp lists in ``setup.py``, you'll
|
||||
get a specific version of Framework (0.9.4) and at least the 0.2 version of
|
||||
Library. (You might think you could list these specific versions in MyApp's
|
||||
``setup.py`` -- but if you do that you'll have to edit MyApp if you want to
|
||||
try a new version of Framework, or release a new version of MyApp if you
|
||||
determine that Library 0.3 doesn't work with your application.) You can also
|
||||
add optional libraries and support tools that MyApp doesn't strictly
|
||||
require, giving people a set of recommended libraries.
|
||||
|
||||
You can also include "editable" packages -- packages that are checked out from
|
||||
Subversion, Git, Mercurial and Bazaar. These are just like using the ``-e``
|
||||
option to pip. They look like::
|
||||
|
||||
-e svn+http://myrepo/svn/MyApp#egg=MyApp
|
||||
|
||||
You have to start the URL with ``svn+`` (``git+``, ``hg+`` or ``bzr+``), and
|
||||
you have to include ``#egg=Package`` so pip knows what to expect at that URL.
|
||||
You can also include ``@rev`` in the URL, e.g., ``@275`` to check out
|
||||
revision 275.
|
||||
|
||||
Requirement files are mostly *flat*. Maybe ``MyApp`` requires
|
||||
``Framework``, and ``Framework`` requires ``Library``. I encourage
|
||||
you to still list all these in a single requirement file; it is the
|
||||
nature of Python programs that there are implicit bindings *directly*
|
||||
between MyApp and Library. For instance, Framework might expose one
|
||||
of Library's objects, and so if Library is updated it might directly
|
||||
break MyApp. If that happens you can update the requirements file to
|
||||
force an earlier version of Library, and you can do that without
|
||||
having to re-release MyApp at all.
|
||||
|
||||
Read the `requirements file format`_ to learn about other features.
|
||||
|
||||
Freezing Requirements
|
||||
=====================
|
||||
|
||||
So you have a working set of packages, and you want to be able to install them
|
||||
elsewhere. `Requirements files`_ let you install exact versions, but it won't
|
||||
tell you what all the exact versions are.
|
||||
|
||||
To create a new requirements file from a known working environment, use::
|
||||
|
||||
$ pip freeze > stable-req.txt
|
||||
|
||||
This will write a listing of *all* installed libraries to ``stable-req.txt``
|
||||
with exact versions for every library. You may want to edit the file down after
|
||||
generating (e.g., to eliminate unnecessary libraries), but it'll give you a
|
||||
stable starting point for constructing your requirements file.
|
||||
|
||||
You can also give it an existing requirements file, and it will use that as a
|
||||
sort of template for the new file. So if you do::
|
||||
|
||||
$ pip freeze -r devel-req.txt > stable-req.txt
|
||||
|
||||
it will keep the packages listed in ``devel-req.txt`` in order and preserve
|
||||
comments.
|
||||
|
||||
The _`requirements file format`
|
||||
===============================
|
||||
|
||||
The requirements file is a way to get pip to install specific packages
|
||||
to make up an *environment*. This document describes that format. To
|
||||
read about *when* you should use requirement files, see `Requirements
|
||||
Files <./#requirements-files>`_.
|
||||
|
||||
Each line of the requirements file indicates something to be
|
||||
installed. For example::
|
||||
|
||||
MyPackage==3.0
|
||||
|
||||
tells pip to install the 3.0 version of MyPackage.
|
||||
|
||||
You can also request `extras`_ in the requirements file::
|
||||
|
||||
MyPackage==3.0 [PDF]
|
||||
|
||||
.. _extras: http://peak.telecommunity.com/DevCenter/setuptools#declaring-extras-optional-features-with-their-own-dependencies
|
||||
|
||||
Packages may also be installed in an "editable" form. This puts the
|
||||
source code into ``src/distname`` (making the name lower case) and
|
||||
runs ``python setup.py develop`` on the package. To indicate
|
||||
editable, use ``-e``, like::
|
||||
|
||||
-e svn+http://svn.myproject.org/svn/MyProject/trunk#egg=MyProject
|
||||
|
||||
The ``#egg=MyProject`` part is important, because while you can
|
||||
install simply given the svn location, the project name is useful in
|
||||
other places.
|
||||
|
||||
You can also specify the egg name for a non-editable url. This is useful to
|
||||
point to HEAD locations on the local filesystem:
|
||||
|
||||
file:///path/to/your/lib/project#egg=MyProject
|
||||
|
||||
or relative paths:
|
||||
|
||||
file:../../lib/project#egg=MyProject
|
||||
|
||||
If you need to give pip (and by association easy_install) hints
|
||||
about where to find a package, you can use the ``-f``
|
||||
(``--find-links``) option, like::
|
||||
|
||||
$ pip -f http://someserver.org/index-of-packages MyPackage==3.0
|
||||
|
||||
Pip will then look for a link at http://someserver.org/index-of-packages
|
||||
that matches version ``3.0`` of ``MyPackage`` -- the link should be
|
||||
like ``MyPackage-3.0.tar.gz``.
|
||||
|
||||
And if you want to install from a tarball or zip file with a direct link,
|
||||
you don't need ``-f`` option, you just need to pass the absolute url, like::
|
||||
|
||||
$ pip install http://someserver.org/packages/MyPackage-3.0.tar.gz
|
||||
|
||||
|
||||
Version Control
|
||||
---------------
|
||||
|
||||
Right now pip knows of the following major version control systems:
|
||||
|
||||
Subversion
|
||||
~~~~~~~~~~
|
||||
|
||||
Pip supports the URL schemes ``svn``, ``svn+svn``, ``svn+http``, ``svn+https``, ``svn+ssh``.
|
||||
You can also give specific revisions to an SVN URL, like::
|
||||
|
||||
-e svn+svn://svn.myproject.org/svn/MyProject#egg=MyProject
|
||||
-e svn+http://svn.myproject.org/svn/MyProject/trunk@2019#egg=MyProject
|
||||
|
||||
which will check out revision 2019. ``@{20080101}`` would also check
|
||||
out the revision from 2008-01-01. You can only check out specific
|
||||
revisions using ``-e svn+...``.
|
||||
|
||||
Git
|
||||
~~~
|
||||
|
||||
Pip currently supports cloning over ``git``, ``git+http`` and ``git+ssh``::
|
||||
|
||||
-e git://git.myproject.org/MyProject.git#egg=MyProject
|
||||
-e git+http://git.myproject.org/MyProject/#egg=MyProject
|
||||
-e git+ssh://git@myproject.org/MyProject/#egg=MyProject
|
||||
|
||||
Passing branch names, a commit hash or a tag name is also possible::
|
||||
|
||||
-e git://git.myproject.org/MyProject.git@master#egg=MyProject
|
||||
-e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
|
||||
-e git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject
|
||||
|
||||
Mercurial
|
||||
~~~~~~~~~
|
||||
|
||||
The supported schemes are: ``hg+http``, ``hg+https``,
|
||||
``hg+static-http`` and ``hg+ssh``::
|
||||
|
||||
-e hg+http://hg.myproject.org/MyProject/#egg=MyProject
|
||||
-e hg+https://hg.myproject.org/MyProject/#egg=MyProject
|
||||
-e hg+ssh://hg@myproject.org/MyProject/#egg=MyProject
|
||||
|
||||
You can also specify a revision number, a revision hash, a tag name or a local
|
||||
branch name::
|
||||
|
||||
-e hg+http://hg.myproject.org/MyProject/@da39a3ee5e6b#egg=MyProject
|
||||
-e hg+http://hg.myproject.org/MyProject/@2019#egg=MyProject
|
||||
-e hg+http://hg.myproject.org/MyProject/@v1.0#egg=MyProject
|
||||
-e hg+http://hg.myproject.org/MyProject/@special_feature#egg=MyProject
|
||||
|
||||
Bazaar
|
||||
~~~~~~
|
||||
|
||||
Pip supports Bazaar using the ``bzr+http``, ``bzr+https``, ``bzr+ssh``,
|
||||
``bzr+sftp``, ``bzr+ftp`` and ``bzr+lp`` schemes::
|
||||
|
||||
-e bzr+http://bzr.myproject.org/MyProject/trunk/#egg=MyProject
|
||||
-e bzr+sftp://user@myproject.org/MyProject/trunk/#egg=MyProject
|
||||
-e bzr+ssh://user@myproject.org/MyProject/trunk/#egg=MyProject
|
||||
-e bzr+ftp://user@myproject.org/MyProject/trunk/#egg=MyProject
|
||||
-e bzr+lp:MyProject#egg=MyProject
|
||||
|
||||
Tags or revisions can be installed like this::
|
||||
|
||||
-e bzr+https://bzr.myproject.org/MyProject/trunk/@2019#egg=MyProject
|
||||
-e bzr+http://bzr.myproject.org/MyProject/trunk/@v1.0#egg=MyProject
|
||||
|
||||
Recursive Requirements
|
||||
----------------------
|
||||
|
||||
If you wish, you can also refer to other requirements files, like::
|
||||
|
||||
-r Pylons-requirements.txt
|
||||
|
||||
This gives you a way of abstracting out sets of requirements. This
|
||||
isn't, however, very friendly with `frozen requirements
|
||||
<./#freezing-requirements>`_, as everything in
|
||||
``Pylons-requirements.txt`` will show up in your frozen file.
|
||||
|
||||
Indexes, find-links
|
||||
-------------------
|
||||
|
||||
You can also provide values for the ``--index-url`` and ``--find-links``
|
||||
options in your requirement files, like::
|
||||
|
||||
--index-url http://example.com/private-pypi/
|
||||
|
||||
Note that using ``--index-url`` removes the use of `PyPI
|
||||
<http://pypi.python.org>`_, while using ``--extra-index-url`` will add
|
||||
additional indexes.
|
||||
|
||||
``--find-links`` is more ad-hoc; instead of a complete "index", you
|
||||
only need an HTML page of links to available packages. Simply by
|
||||
putting all your private packages in a directory and using the Apache
|
||||
auto-index, you can publish your packages so pip can find them.
|
||||
``--find-links`` is always additive; pip looks at everything it can
|
||||
find. Use it like::
|
||||
|
||||
--find-links http://example.com/private-packages/
|
||||
|
||||
Note that all these options must be on a line of their own.
|
||||
Vendored
-160
@@ -1,160 +0,0 @@
|
||||
=====
|
||||
Usage
|
||||
=====
|
||||
|
||||
Install packages
|
||||
----------------
|
||||
|
||||
The simplest way to install a package is by specifying its name::
|
||||
|
||||
$ pip install SomePackage
|
||||
|
||||
`SomePackage` is downloaded from :term:`PyPI`, along with its
|
||||
dependencies, and installed.
|
||||
|
||||
If `SomePackage` is already installed, and you need a newer version, use ``pip
|
||||
install --upgrade SomePackage``. You can also request a specific version (``pip
|
||||
install SomePackage==1.0.4``) and specify `setuptools extras`_ (``pip install
|
||||
SomePackage[PDF]``).
|
||||
|
||||
You can also install from a particular source distribution file, either
|
||||
local or remote::
|
||||
|
||||
$ pip install ./downloads/SomePackage-1.0.4.tar.gz
|
||||
$ pip install http://my.package.repo/SomePackage-1.0.4.zip
|
||||
|
||||
.. _setuptools extras: http://peak.telecommunity.com/DevCenter/setuptools#declaring-extras-optional-features-with-their-own-dependencies
|
||||
|
||||
|
||||
Edit mode
|
||||
*********
|
||||
|
||||
Packages normally_ install under ``site-packages``, but when you're
|
||||
making changes, it makes more sense to run the package straight from the
|
||||
checked-out source tree. "Editable" installs create a ``.pth`` file in
|
||||
``site-packages`` that extends Python's import path to find the
|
||||
package::
|
||||
|
||||
$ pip install -e path/to/SomePackage
|
||||
|
||||
.. _normally: http://docs.python.org/install/index.html#how-installation-works
|
||||
|
||||
|
||||
Version control systems
|
||||
***********************
|
||||
|
||||
Pip knows how to check out a package from version control. `Subversion`,
|
||||
`Git`, `Mercurial` and `Bazaar` are supported. The repository will be
|
||||
checked out in a temporary folder, installed, and cleaned up::
|
||||
|
||||
$ pip install git+https://github.com/simplejson/simplejson.git
|
||||
$ pip install svn+svn://svn.zope.org/repos/main/zope.interface/trunk/
|
||||
|
||||
This can be combined with the `-e` flag, and Pip will perform the
|
||||
checkout in ``./src/``. You need to supply a name for the checkout
|
||||
folder by appending a hash to the repository URL::
|
||||
|
||||
$ pip install -e git+https://github.com/lakshmivyas/hyde.git#egg=hyde
|
||||
|
||||
Note that only basic checking-out of a repo is supported; pip will not
|
||||
handle advanced VCS-specific features such as submodules or subrepos.
|
||||
|
||||
|
||||
Alternate package repositories
|
||||
******************************
|
||||
|
||||
pip searches in :term:`PyPI` by default, but this can be overridden using the
|
||||
``--index-url`` option::
|
||||
|
||||
$ pip install --index-url http://d.pypi.python.org/simple/ SomePackage
|
||||
|
||||
If you have your own package index with a few additional packages, you may want
|
||||
to to specify additional index URLs while still also using :term:`PyPI`::
|
||||
|
||||
$ pip install --extra-index-url http://my.package.repo/ SomePackage
|
||||
|
||||
A "package index" used with ``--index-url`` or ``--extra-index-url`` can be as
|
||||
simple as a static-web-served directory, with automatic indexes on, with a
|
||||
subdirectory per package and sdists (tarballs created with ``python setup.py
|
||||
sdist``) in that directory::
|
||||
|
||||
mypackage/
|
||||
mypackage-0.7.8.tar.gz
|
||||
mypackage-1.0.1.tar.gz
|
||||
otherpackage/
|
||||
otherpackage-2.3.5.tar.gz
|
||||
|
||||
If the number of packages in the index is small, it's even simpler to skip the
|
||||
subdirectories: put all of the sdists in a single directory and use pip's
|
||||
``--find-links`` option with a URL to that directory::
|
||||
|
||||
mypackage-0.7.8.tar.gz
|
||||
mypackage-1.0.1.tar.gz
|
||||
otherpackage-2.3.5.tar.gz
|
||||
|
||||
``--find-links`` also supports local paths, so installation need not require a
|
||||
network connection.
|
||||
|
||||
Like ``--extra-index-url``, ``--find-links`` is additive by default, it does
|
||||
not replace or supersede the index. All package sources are checked, and the
|
||||
latest qualifying version for every requested package is used. If you want only
|
||||
your ``-find-links`` URL used as package source, you need to pair it with
|
||||
``--no-index``.
|
||||
|
||||
``--index-url``, ``--extra-index-url`` and ``--find-links`` can all be used
|
||||
within a :ref:`requirements file <requirements-files>` in addition to on the
|
||||
command line directly.
|
||||
|
||||
|
||||
Uninstall packages
|
||||
------------------
|
||||
|
||||
pip is able to uninstall most installed packages with ``pip uninstall
|
||||
package-name``.
|
||||
|
||||
Known exceptions include pure-distutils packages installed with
|
||||
``python setup.py install`` (such packages leave behind no metadata allowing
|
||||
determination of what files were installed), and script wrappers installed
|
||||
by develop-installs (``python setup.py develop``).
|
||||
|
||||
pip also performs an automatic uninstall of an old version of a package
|
||||
before upgrading to a newer version, so outdated files (and egg-info data)
|
||||
from conflicting versions aren't left hanging around to cause trouble. The
|
||||
old version of the package is automatically restored if the new version
|
||||
fails to download or install.
|
||||
|
||||
|
||||
Searching for packages
|
||||
----------------------
|
||||
|
||||
pip can search :term:`PyPI` for packages using the ``pip search``
|
||||
command::
|
||||
|
||||
$ pip search "query"
|
||||
|
||||
The query will be used to search the names and summaries of all
|
||||
packages. With the ``--index`` option you can search in a different
|
||||
repository.
|
||||
|
||||
|
||||
Bundles
|
||||
-------
|
||||
|
||||
Another way to distribute a set of libraries is a bundle format (specific to
|
||||
pip). This format is not stable at this time (there simply hasn't been
|
||||
any feedback, nor a great deal of thought). A bundle file contains all the
|
||||
source for your package, and you can have pip install them all together.
|
||||
Once you have the bundle file further network access won't be necessary. To
|
||||
build a bundle file, do::
|
||||
|
||||
$ pip bundle MyApp.pybundle MyApp
|
||||
|
||||
(Using a :ref:`requirements file <requirements-files>` would be wise.) Then
|
||||
someone else can get the file ``MyApp.pybundle`` and run::
|
||||
|
||||
$ pip install MyApp.pybundle
|
||||
|
||||
This is *not* a binary format. This only packages source. If you have binary
|
||||
packages, then the person who installs the files will have to have a compiler,
|
||||
any necessary headers installed, etc. Binary packages are hard, this is
|
||||
relatively easy.
|
||||
Vendored
-592
@@ -1,592 +0,0 @@
|
||||
"""Utilities to support packages."""
|
||||
|
||||
# NOTE: This module must remain compatible with Python 2.3, as it is shared
|
||||
# by setuptools for distribution with Python 2.3 and up.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import imp
|
||||
import os.path
|
||||
from types import ModuleType
|
||||
|
||||
__all__ = [
|
||||
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
|
||||
'walk_packages', 'iter_modules',
|
||||
'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
|
||||
]
|
||||
|
||||
|
||||
def read_code(stream):
|
||||
# This helper is needed in order for the PEP 302 emulation to
|
||||
# correctly handle compiled files
|
||||
import marshal
|
||||
|
||||
magic = stream.read(4)
|
||||
if magic != imp.get_magic():
|
||||
return None
|
||||
|
||||
stream.read(4) # Skip timestamp
|
||||
return marshal.load(stream)
|
||||
|
||||
|
||||
def simplegeneric(func):
|
||||
"""Make a trivial single-dispatch generic function"""
|
||||
registry = {}
|
||||
|
||||
def wrapper(*args, **kw):
|
||||
ob = args[0]
|
||||
try:
|
||||
cls = ob.__class__
|
||||
except AttributeError:
|
||||
cls = type(ob)
|
||||
try:
|
||||
mro = cls.__mro__
|
||||
except AttributeError:
|
||||
try:
|
||||
|
||||
class cls(cls, object):
|
||||
pass
|
||||
|
||||
mro = cls.__mro__[1:]
|
||||
except TypeError:
|
||||
mro = object, # must be an ExtensionClass or some such :(
|
||||
for t in mro:
|
||||
if t in registry:
|
||||
return registry[t](*args, **kw)
|
||||
else:
|
||||
return func(*args, **kw)
|
||||
try:
|
||||
wrapper.__name__ = func.__name__
|
||||
except (TypeError, AttributeError):
|
||||
pass # Python 2.3 doesn't allow functions to be renamed
|
||||
|
||||
def register(typ, func=None):
|
||||
if func is None:
|
||||
return lambda f: register(typ, f)
|
||||
registry[typ] = func
|
||||
return func
|
||||
|
||||
wrapper.__dict__ = func.__dict__
|
||||
wrapper.__doc__ = func.__doc__
|
||||
wrapper.register = register
|
||||
return wrapper
|
||||
|
||||
|
||||
def walk_packages(path=None, prefix='', onerror=None):
|
||||
"""Yields (module_loader, name, ispkg) for all modules recursively
|
||||
on path, or, if path is None, all accessible modules.
|
||||
|
||||
'path' should be either None or a list of paths to look for
|
||||
modules in.
|
||||
|
||||
'prefix' is a string to output on the front of every module name
|
||||
on output.
|
||||
|
||||
Note that this function must import all *packages* (NOT all
|
||||
modules!) on the given path, in order to access the __path__
|
||||
attribute to find submodules.
|
||||
|
||||
'onerror' is a function which gets called with one argument (the
|
||||
name of the package which was being imported) if any exception
|
||||
occurs while trying to import a package. If no onerror function is
|
||||
supplied, ImportErrors are caught and ignored, while all other
|
||||
exceptions are propagated, terminating the search.
|
||||
|
||||
Examples:
|
||||
|
||||
# list all modules python can access
|
||||
walk_packages()
|
||||
|
||||
# list all submodules of ctypes
|
||||
walk_packages(ctypes.__path__, ctypes.__name__+'.')
|
||||
"""
|
||||
|
||||
def seen(p, m={}):
|
||||
if p in m:
|
||||
return True
|
||||
m[p] = True
|
||||
|
||||
for importer, name, ispkg in iter_modules(path, prefix):
|
||||
yield importer, name, ispkg
|
||||
|
||||
if ispkg:
|
||||
try:
|
||||
__import__(name)
|
||||
except ImportError:
|
||||
if onerror is not None:
|
||||
onerror(name)
|
||||
except Exception:
|
||||
if onerror is not None:
|
||||
onerror(name)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
path = getattr(sys.modules[name], '__path__', None) or []
|
||||
|
||||
# don't traverse path items we've seen before
|
||||
path = [p for p in path if not seen(p)]
|
||||
|
||||
for item in walk_packages(path, name+'.', onerror):
|
||||
yield item
|
||||
|
||||
|
||||
def iter_modules(path=None, prefix=''):
|
||||
"""Yields (module_loader, name, ispkg) for all submodules on path,
|
||||
or, if path is None, all top-level modules on sys.path.
|
||||
|
||||
'path' should be either None or a list of paths to look for
|
||||
modules in.
|
||||
|
||||
'prefix' is a string to output on the front of every module name
|
||||
on output.
|
||||
"""
|
||||
|
||||
if path is None:
|
||||
importers = iter_importers()
|
||||
else:
|
||||
importers = map(get_importer, path)
|
||||
|
||||
yielded = {}
|
||||
for i in importers:
|
||||
for name, ispkg in iter_importer_modules(i, prefix):
|
||||
if name not in yielded:
|
||||
yielded[name] = 1
|
||||
yield i, name, ispkg
|
||||
|
||||
|
||||
#@simplegeneric
|
||||
def iter_importer_modules(importer, prefix=''):
|
||||
if not hasattr(importer, 'iter_modules'):
|
||||
return []
|
||||
return importer.iter_modules(prefix)
|
||||
|
||||
iter_importer_modules = simplegeneric(iter_importer_modules)
|
||||
|
||||
|
||||
class ImpImporter:
|
||||
"""PEP 302 Importer that wraps Python's "classic" import algorithm
|
||||
|
||||
ImpImporter(dirname) produces a PEP 302 importer that searches that
|
||||
directory. ImpImporter(None) produces a PEP 302 importer that searches
|
||||
the current sys.path, plus any modules that are frozen or built-in.
|
||||
|
||||
Note that ImpImporter does not currently support being used by placement
|
||||
on sys.meta_path.
|
||||
"""
|
||||
|
||||
def __init__(self, path=None):
|
||||
self.path = path
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
# Note: we ignore 'path' argument since it is only used via meta_path
|
||||
subname = fullname.split(".")[-1]
|
||||
if subname != fullname and self.path is None:
|
||||
return None
|
||||
if self.path is None:
|
||||
path = None
|
||||
else:
|
||||
path = [os.path.realpath(self.path)]
|
||||
try:
|
||||
file, filename, etc = imp.find_module(subname, path)
|
||||
except ImportError:
|
||||
return None
|
||||
return ImpLoader(fullname, file, filename, etc)
|
||||
|
||||
def iter_modules(self, prefix=''):
|
||||
if self.path is None or not os.path.isdir(self.path):
|
||||
return
|
||||
|
||||
yielded = {}
|
||||
import inspect
|
||||
|
||||
filenames = os.listdir(self.path)
|
||||
filenames.sort() # handle packages before same-named modules
|
||||
|
||||
for fn in filenames:
|
||||
modname = inspect.getmodulename(fn)
|
||||
if modname=='__init__' or modname in yielded:
|
||||
continue
|
||||
|
||||
path = os.path.join(self.path, fn)
|
||||
ispkg = False
|
||||
|
||||
if not modname and os.path.isdir(path) and '.' not in fn:
|
||||
modname = fn
|
||||
for fn in os.listdir(path):
|
||||
subname = inspect.getmodulename(fn)
|
||||
if subname=='__init__':
|
||||
ispkg = True
|
||||
break
|
||||
else:
|
||||
continue # not a package
|
||||
|
||||
if modname and '.' not in modname:
|
||||
yielded[modname] = 1
|
||||
yield prefix + modname, ispkg
|
||||
|
||||
|
||||
class ImpLoader:
|
||||
"""PEP 302 Loader that wraps Python's "classic" import algorithm
|
||||
"""
|
||||
code = source = None
|
||||
|
||||
def __init__(self, fullname, file, filename, etc):
|
||||
self.file = file
|
||||
self.filename = filename
|
||||
self.fullname = fullname
|
||||
self.etc = etc
|
||||
|
||||
def load_module(self, fullname):
|
||||
self._reopen()
|
||||
try:
|
||||
mod = imp.load_module(fullname, self.file, self.filename, self.etc)
|
||||
finally:
|
||||
if self.file:
|
||||
self.file.close()
|
||||
# Note: we don't set __loader__ because we want the module to look
|
||||
# normal; i.e. this is just a wrapper for standard import machinery
|
||||
return mod
|
||||
|
||||
def get_data(self, pathname):
|
||||
return open(pathname, "rb").read()
|
||||
|
||||
def _reopen(self):
|
||||
if self.file and self.file.closed:
|
||||
mod_type = self.etc[2]
|
||||
if mod_type==imp.PY_SOURCE:
|
||||
self.file = open(self.filename, 'rU')
|
||||
elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
|
||||
self.file = open(self.filename, 'rb')
|
||||
|
||||
def _fix_name(self, fullname):
|
||||
if fullname is None:
|
||||
fullname = self.fullname
|
||||
elif fullname != self.fullname:
|
||||
raise ImportError("Loader for module %s cannot handle "
|
||||
"module %s" % (self.fullname, fullname))
|
||||
return fullname
|
||||
|
||||
def is_package(self, fullname):
|
||||
fullname = self._fix_name(fullname)
|
||||
return self.etc[2]==imp.PKG_DIRECTORY
|
||||
|
||||
def get_code(self, fullname=None):
|
||||
fullname = self._fix_name(fullname)
|
||||
if self.code is None:
|
||||
mod_type = self.etc[2]
|
||||
if mod_type==imp.PY_SOURCE:
|
||||
source = self.get_source(fullname)
|
||||
self.code = compile(source, self.filename, 'exec')
|
||||
elif mod_type==imp.PY_COMPILED:
|
||||
self._reopen()
|
||||
try:
|
||||
self.code = read_code(self.file)
|
||||
finally:
|
||||
self.file.close()
|
||||
elif mod_type==imp.PKG_DIRECTORY:
|
||||
self.code = self._get_delegate().get_code()
|
||||
return self.code
|
||||
|
||||
def get_source(self, fullname=None):
|
||||
fullname = self._fix_name(fullname)
|
||||
if self.source is None:
|
||||
mod_type = self.etc[2]
|
||||
if mod_type==imp.PY_SOURCE:
|
||||
self._reopen()
|
||||
try:
|
||||
self.source = self.file.read()
|
||||
finally:
|
||||
self.file.close()
|
||||
elif mod_type==imp.PY_COMPILED:
|
||||
if os.path.exists(self.filename[:-1]):
|
||||
f = open(self.filename[:-1], 'rU')
|
||||
self.source = f.read()
|
||||
f.close()
|
||||
elif mod_type==imp.PKG_DIRECTORY:
|
||||
self.source = self._get_delegate().get_source()
|
||||
return self.source
|
||||
|
||||
def _get_delegate(self):
|
||||
return ImpImporter(self.filename).find_module('__init__')
|
||||
|
||||
def get_filename(self, fullname=None):
|
||||
fullname = self._fix_name(fullname)
|
||||
mod_type = self.etc[2]
|
||||
if self.etc[2]==imp.PKG_DIRECTORY:
|
||||
return self._get_delegate().get_filename()
|
||||
elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
|
||||
return self.filename
|
||||
return None
|
||||
|
||||
|
||||
try:
|
||||
import zipimport
|
||||
from zipimport import zipimporter
|
||||
|
||||
def iter_zipimport_modules(importer, prefix=''):
|
||||
dirlist = list(zipimport._zip_directory_cache[importer.archive].keys())
|
||||
dirlist.sort()
|
||||
_prefix = importer.prefix
|
||||
plen = len(_prefix)
|
||||
yielded = {}
|
||||
import inspect
|
||||
for fn in dirlist:
|
||||
if not fn.startswith(_prefix):
|
||||
continue
|
||||
|
||||
fn = fn[plen:].split(os.sep)
|
||||
|
||||
if len(fn)==2 and fn[1].startswith('__init__.py'):
|
||||
if fn[0] not in yielded:
|
||||
yielded[fn[0]] = 1
|
||||
yield fn[0], True
|
||||
|
||||
if len(fn)!=1:
|
||||
continue
|
||||
|
||||
modname = inspect.getmodulename(fn[0])
|
||||
if modname=='__init__':
|
||||
continue
|
||||
|
||||
if modname and '.' not in modname and modname not in yielded:
|
||||
yielded[modname] = 1
|
||||
yield prefix + modname, False
|
||||
|
||||
iter_importer_modules.register(zipimporter, iter_zipimport_modules)
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def get_importer(path_item):
|
||||
"""Retrieve a PEP 302 importer for the given path item
|
||||
|
||||
The returned importer is cached in sys.path_importer_cache
|
||||
if it was newly created by a path hook.
|
||||
|
||||
If there is no importer, a wrapper around the basic import
|
||||
machinery is returned. This wrapper is never inserted into
|
||||
the importer cache (None is inserted instead).
|
||||
|
||||
The cache (or part of it) can be cleared manually if a
|
||||
rescan of sys.path_hooks is necessary.
|
||||
"""
|
||||
try:
|
||||
importer = sys.path_importer_cache[path_item]
|
||||
except KeyError:
|
||||
for path_hook in sys.path_hooks:
|
||||
try:
|
||||
importer = path_hook(path_item)
|
||||
break
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
importer = None
|
||||
sys.path_importer_cache.setdefault(path_item, importer)
|
||||
|
||||
if importer is None:
|
||||
try:
|
||||
importer = ImpImporter(path_item)
|
||||
except ImportError:
|
||||
importer = None
|
||||
return importer
|
||||
|
||||
|
||||
def iter_importers(fullname=""):
|
||||
"""Yield PEP 302 importers for the given module name
|
||||
|
||||
If fullname contains a '.', the importers will be for the package
|
||||
containing fullname, otherwise they will be importers for sys.meta_path,
|
||||
sys.path, and Python's "classic" import machinery, in that order. If
|
||||
the named module is in a package, that package is imported as a side
|
||||
effect of invoking this function.
|
||||
|
||||
Non PEP 302 mechanisms (e.g. the Windows registry) used by the
|
||||
standard import machinery to find files in alternative locations
|
||||
are partially supported, but are searched AFTER sys.path. Normally,
|
||||
these locations are searched BEFORE sys.path, preventing sys.path
|
||||
entries from shadowing them.
|
||||
|
||||
For this to cause a visible difference in behaviour, there must
|
||||
be a module or package name that is accessible via both sys.path
|
||||
and one of the non PEP 302 file system mechanisms. In this case,
|
||||
the emulation will find the former version, while the builtin
|
||||
import mechanism will find the latter.
|
||||
|
||||
Items of the following types can be affected by this discrepancy:
|
||||
imp.C_EXTENSION, imp.PY_SOURCE, imp.PY_COMPILED, imp.PKG_DIRECTORY
|
||||
"""
|
||||
if fullname.startswith('.'):
|
||||
raise ImportError("Relative module names not supported")
|
||||
if '.' in fullname:
|
||||
# Get the containing package's __path__
|
||||
pkg = '.'.join(fullname.split('.')[:-1])
|
||||
if pkg not in sys.modules:
|
||||
__import__(pkg)
|
||||
path = getattr(sys.modules[pkg], '__path__', None) or []
|
||||
else:
|
||||
for importer in sys.meta_path:
|
||||
yield importer
|
||||
path = sys.path
|
||||
for item in path:
|
||||
yield get_importer(item)
|
||||
if '.' not in fullname:
|
||||
yield ImpImporter()
|
||||
|
||||
|
||||
def get_loader(module_or_name):
|
||||
"""Get a PEP 302 "loader" object for module_or_name
|
||||
|
||||
If the module or package is accessible via the normal import
|
||||
mechanism, a wrapper around the relevant part of that machinery
|
||||
is returned. Returns None if the module cannot be found or imported.
|
||||
If the named module is not already imported, its containing package
|
||||
(if any) is imported, in order to establish the package __path__.
|
||||
|
||||
This function uses iter_importers(), and is thus subject to the same
|
||||
limitations regarding platform-specific special import locations such
|
||||
as the Windows registry.
|
||||
"""
|
||||
if module_or_name in sys.modules:
|
||||
module_or_name = sys.modules[module_or_name]
|
||||
if isinstance(module_or_name, ModuleType):
|
||||
module = module_or_name
|
||||
loader = getattr(module, '__loader__', None)
|
||||
if loader is not None:
|
||||
return loader
|
||||
fullname = module.__name__
|
||||
else:
|
||||
fullname = module_or_name
|
||||
return find_loader(fullname)
|
||||
|
||||
|
||||
def find_loader(fullname):
|
||||
"""Find a PEP 302 "loader" object for fullname
|
||||
|
||||
If fullname contains dots, path must be the containing package's __path__.
|
||||
Returns None if the module cannot be found or imported. This function uses
|
||||
iter_importers(), and is thus subject to the same limitations regarding
|
||||
platform-specific special import locations such as the Windows registry.
|
||||
"""
|
||||
for importer in iter_importers(fullname):
|
||||
loader = importer.find_module(fullname)
|
||||
if loader is not None:
|
||||
return loader
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def extend_path(path, name):
|
||||
"""Extend a package's path.
|
||||
|
||||
Intended use is to place the following code in a package's __init__.py:
|
||||
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
This will add to the package's __path__ all subdirectories of
|
||||
directories on sys.path named after the package. This is useful
|
||||
if one wants to distribute different parts of a single logical
|
||||
package as multiple directories.
|
||||
|
||||
It also looks for *.pkg files beginning where * matches the name
|
||||
argument. This feature is similar to *.pth files (see site.py),
|
||||
except that it doesn't special-case lines starting with 'import'.
|
||||
A *.pkg file is trusted at face value: apart from checking for
|
||||
duplicates, all entries found in a *.pkg file are added to the
|
||||
path, regardless of whether they are exist the filesystem. (This
|
||||
is a feature.)
|
||||
|
||||
If the input path is not a list (as is the case for frozen
|
||||
packages) it is returned unchanged. The input path is not
|
||||
modified; an extended copy is returned. Items are only appended
|
||||
to the copy at the end.
|
||||
|
||||
It is assumed that sys.path is a sequence. Items of sys.path that
|
||||
are not (unicode or 8-bit) strings referring to existing
|
||||
directories are ignored. Unicode items of sys.path that cause
|
||||
errors when used as filenames may cause this function to raise an
|
||||
exception (in line with os.path.isdir() behavior).
|
||||
"""
|
||||
|
||||
if not isinstance(path, list):
|
||||
# This could happen e.g. when this is called from inside a
|
||||
# frozen package. Return the path unchanged in that case.
|
||||
return path
|
||||
|
||||
pname = os.path.join(*name.split('.')) # Reconstitute as relative path
|
||||
# Just in case os.extsep != '.'
|
||||
sname = os.extsep.join(name.split('.'))
|
||||
sname_pkg = sname + os.extsep + "pkg"
|
||||
init_py = "__init__" + os.extsep + "py"
|
||||
|
||||
path = path[:] # Start with a copy of the existing path
|
||||
|
||||
from pip.backwardcompat import string_types
|
||||
|
||||
for dir in sys.path:
|
||||
if not isinstance(dir, string_types) or not os.path.isdir(dir):
|
||||
continue
|
||||
subdir = os.path.join(dir, pname)
|
||||
# XXX This may still add duplicate entries to path on
|
||||
# case-insensitive filesystems
|
||||
initfile = os.path.join(subdir, init_py)
|
||||
if subdir not in path and os.path.isfile(initfile):
|
||||
path.append(subdir)
|
||||
# XXX Is this the right thing for subpackages like zope.app?
|
||||
# It looks for a file named "zope.app.pkg"
|
||||
pkgfile = os.path.join(dir, sname_pkg)
|
||||
if os.path.isfile(pkgfile):
|
||||
try:
|
||||
f = open(pkgfile)
|
||||
except IOError:
|
||||
msg = sys.exc_info()[1]
|
||||
sys.stderr.write("Can't open %s: %s\n" %
|
||||
(pkgfile, msg))
|
||||
else:
|
||||
for line in f:
|
||||
line = line.rstrip('\n')
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
path.append(line) # Don't check for existence!
|
||||
f.close()
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def get_data(package, resource):
|
||||
"""Get a resource from a package.
|
||||
|
||||
This is a wrapper round the PEP 302 loader get_data API. The package
|
||||
argument should be the name of a package, in standard module format
|
||||
(foo.bar). The resource argument should be in the form of a relative
|
||||
filename, using '/' as the path separator. The parent directory name '..'
|
||||
is not allowed, and nor is a rooted name (starting with a '/').
|
||||
|
||||
The function returns a binary string, which is the contents of the
|
||||
specified resource.
|
||||
|
||||
For packages located in the filesystem, which have already been imported,
|
||||
this is the rough equivalent of
|
||||
|
||||
d = os.path.dirname(sys.modules[package].__file__)
|
||||
data = open(os.path.join(d, resource), 'rb').read()
|
||||
|
||||
If the package cannot be located or loaded, or it uses a PEP 302 loader
|
||||
which does not support get_data(), then None is returned.
|
||||
"""
|
||||
|
||||
loader = get_loader(package)
|
||||
if loader is None or not hasattr(loader, 'get_data'):
|
||||
return None
|
||||
mod = sys.modules.get(package) or loader.load_module(package)
|
||||
if mod is None or not hasattr(mod, '__file__'):
|
||||
return None
|
||||
|
||||
# Modify the resource name to be compatible with the loader.get_data
|
||||
# signature - an os.path format "filename" starting with the dirname of
|
||||
# the package's __file__
|
||||
parts = resource.split('/')
|
||||
parts.insert(0, os.path.dirname(mod.__file__))
|
||||
resource_name = os.path.join(*parts)
|
||||
return loader.get_data(resource_name)
|
||||
Vendored
-193
@@ -1,193 +0,0 @@
|
||||
"""Base Command class, and related routines"""
|
||||
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import traceback
|
||||
import time
|
||||
|
||||
from pip import commands
|
||||
from pip.log import logger
|
||||
from pip.baseparser import parser, ConfigOptionParser, UpdatingDefaultsHelpFormatter
|
||||
from pip.download import urlopen
|
||||
from pip.exceptions import (BadCommand, InstallationError, UninstallationError,
|
||||
CommandError)
|
||||
from pip.backwardcompat import StringIO, walk_packages
|
||||
from pip.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND
|
||||
|
||||
|
||||
__all__ = ['command_dict', 'Command', 'load_all_commands',
|
||||
'load_command', 'command_names']
|
||||
|
||||
command_dict = {}
|
||||
|
||||
# for backwards compatibiliy
|
||||
get_proxy = urlopen.get_proxy
|
||||
|
||||
|
||||
class Command(object):
|
||||
name = None
|
||||
usage = None
|
||||
hidden = False
|
||||
|
||||
def __init__(self):
|
||||
assert self.name
|
||||
self.parser = ConfigOptionParser(
|
||||
usage=self.usage,
|
||||
prog='%s %s' % (sys.argv[0], self.name),
|
||||
version=parser.version,
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
name=self.name)
|
||||
for option in parser.option_list:
|
||||
if not option.dest or option.dest == 'help':
|
||||
# -h, --version, etc
|
||||
continue
|
||||
self.parser.add_option(option)
|
||||
command_dict[self.name] = self
|
||||
|
||||
def merge_options(self, initial_options, options):
|
||||
# Make sure we have all global options carried over
|
||||
for attr in ['log', 'proxy', 'require_venv',
|
||||
'log_explicit_levels', 'log_file',
|
||||
'timeout', 'default_vcs',
|
||||
'skip_requirements_regex',
|
||||
'no_input', 'exists_action']:
|
||||
setattr(options, attr, getattr(initial_options, attr) or getattr(options, attr))
|
||||
options.quiet += initial_options.quiet
|
||||
options.verbose += initial_options.verbose
|
||||
|
||||
def setup_logging(self):
|
||||
pass
|
||||
|
||||
def main(self, args, initial_options):
|
||||
options, args = self.parser.parse_args(args)
|
||||
self.merge_options(initial_options, options)
|
||||
|
||||
level = 1 # Notify
|
||||
level += options.verbose
|
||||
level -= options.quiet
|
||||
level = logger.level_for_integer(4-level)
|
||||
complete_log = []
|
||||
logger.consumers.extend(
|
||||
[(level, sys.stdout),
|
||||
(logger.DEBUG, complete_log.append)])
|
||||
if options.log_explicit_levels:
|
||||
logger.explicit_levels = True
|
||||
|
||||
self.setup_logging()
|
||||
|
||||
if options.no_input:
|
||||
os.environ['PIP_NO_INPUT'] = '1'
|
||||
|
||||
if options.exists_action:
|
||||
os.environ['PIP_EXISTS_ACTION'] = ''.join(options.exists_action)
|
||||
|
||||
if options.require_venv:
|
||||
# If a venv is required check if it can really be found
|
||||
if not os.environ.get('VIRTUAL_ENV'):
|
||||
logger.fatal('Could not find an activated virtualenv (required).')
|
||||
sys.exit(VIRTUALENV_NOT_FOUND)
|
||||
|
||||
if options.log:
|
||||
log_fp = open_logfile(options.log, 'a')
|
||||
logger.consumers.append((logger.DEBUG, log_fp))
|
||||
else:
|
||||
log_fp = None
|
||||
|
||||
socket.setdefaulttimeout(options.timeout or None)
|
||||
|
||||
urlopen.setup(proxystr=options.proxy, prompting=not options.no_input)
|
||||
|
||||
exit = SUCCESS
|
||||
store_log = False
|
||||
try:
|
||||
status = self.run(options, args)
|
||||
# FIXME: all commands should return an exit status
|
||||
# and when it is done, isinstance is not needed anymore
|
||||
if isinstance(status, int):
|
||||
exit = status
|
||||
except (InstallationError, UninstallationError):
|
||||
e = sys.exc_info()[1]
|
||||
logger.fatal(str(e))
|
||||
logger.info('Exception information:\n%s' % format_exc())
|
||||
store_log = True
|
||||
exit = ERROR
|
||||
except BadCommand:
|
||||
e = sys.exc_info()[1]
|
||||
logger.fatal(str(e))
|
||||
logger.info('Exception information:\n%s' % format_exc())
|
||||
store_log = True
|
||||
exit = ERROR
|
||||
except CommandError:
|
||||
e = sys.exc_info()[1]
|
||||
logger.fatal('ERROR: %s' % e)
|
||||
logger.info('Exception information:\n%s' % format_exc())
|
||||
exit = ERROR
|
||||
except KeyboardInterrupt:
|
||||
logger.fatal('Operation cancelled by user')
|
||||
logger.info('Exception information:\n%s' % format_exc())
|
||||
store_log = True
|
||||
exit = ERROR
|
||||
except:
|
||||
logger.fatal('Exception:\n%s' % format_exc())
|
||||
store_log = True
|
||||
exit = UNKNOWN_ERROR
|
||||
if log_fp is not None:
|
||||
log_fp.close()
|
||||
if store_log:
|
||||
log_fn = options.log_file
|
||||
text = '\n'.join(complete_log)
|
||||
logger.fatal('Storing complete log in %s' % log_fn)
|
||||
log_fp = open_logfile(log_fn, 'w')
|
||||
log_fp.write(text)
|
||||
log_fp.close()
|
||||
return exit
|
||||
|
||||
|
||||
def format_exc(exc_info=None):
|
||||
if exc_info is None:
|
||||
exc_info = sys.exc_info()
|
||||
out = StringIO()
|
||||
traceback.print_exception(*exc_info, **dict(file=out))
|
||||
return out.getvalue()
|
||||
|
||||
|
||||
def open_logfile(filename, mode='a'):
|
||||
"""Open the named log file in append mode.
|
||||
|
||||
If the file already exists, a separator will also be printed to
|
||||
the file to separate past activity from current activity.
|
||||
"""
|
||||
filename = os.path.expanduser(filename)
|
||||
filename = os.path.abspath(filename)
|
||||
dirname = os.path.dirname(filename)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
exists = os.path.exists(filename)
|
||||
|
||||
log_fp = open(filename, mode)
|
||||
if exists:
|
||||
log_fp.write('%s\n' % ('-'*60))
|
||||
log_fp.write('%s run on %s\n' % (sys.argv[0], time.strftime('%c')))
|
||||
return log_fp
|
||||
|
||||
|
||||
def load_command(name):
|
||||
full_name = 'pip.commands.%s' % name
|
||||
if full_name in sys.modules:
|
||||
return
|
||||
try:
|
||||
__import__(full_name)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def load_all_commands():
|
||||
for name in command_names():
|
||||
load_command(name)
|
||||
|
||||
|
||||
def command_names():
|
||||
names = set((pkg[1] for pkg in walk_packages(path=commands.__path__)))
|
||||
return list(names)
|
||||
|
||||
Vendored
-226
@@ -1,226 +0,0 @@
|
||||
"""Base option parser setup"""
|
||||
|
||||
import sys
|
||||
import optparse
|
||||
import pkg_resources
|
||||
import os
|
||||
from distutils.util import strtobool
|
||||
from pip.backwardcompat import ConfigParser, string_types
|
||||
from pip.locations import default_config_file, default_log_file
|
||||
|
||||
|
||||
class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
|
||||
"""Custom help formatter for use in ConfigOptionParser that updates
|
||||
the defaults before expanding them, allowing them to show up correctly
|
||||
in the help listing"""
|
||||
|
||||
def expand_default(self, option):
|
||||
if self.parser is not None:
|
||||
self.parser.update_defaults(self.parser.defaults)
|
||||
return optparse.IndentedHelpFormatter.expand_default(self, option)
|
||||
|
||||
|
||||
class ConfigOptionParser(optparse.OptionParser):
|
||||
"""Custom option parser which updates its defaults by by checking the
|
||||
configuration files and environmental variables"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.config = ConfigParser.RawConfigParser()
|
||||
self.name = kwargs.pop('name')
|
||||
self.files = self.get_config_files()
|
||||
self.config.read(self.files)
|
||||
assert self.name
|
||||
optparse.OptionParser.__init__(self, *args, **kwargs)
|
||||
|
||||
def get_config_files(self):
|
||||
config_file = os.environ.get('PIP_CONFIG_FILE', False)
|
||||
if config_file and os.path.exists(config_file):
|
||||
return [config_file]
|
||||
return [default_config_file]
|
||||
|
||||
def update_defaults(self, defaults):
|
||||
"""Updates the given defaults with values from the config files and
|
||||
the environ. Does a little special handling for certain types of
|
||||
options (lists)."""
|
||||
# Then go and look for the other sources of configuration:
|
||||
config = {}
|
||||
# 1. config files
|
||||
for section in ('global', self.name):
|
||||
config.update(self.normalize_keys(self.get_config_section(section)))
|
||||
# 2. environmental variables
|
||||
config.update(self.normalize_keys(self.get_environ_vars()))
|
||||
# Then set the options with those values
|
||||
for key, val in config.items():
|
||||
option = self.get_option(key)
|
||||
if option is not None:
|
||||
# ignore empty values
|
||||
if not val:
|
||||
continue
|
||||
# handle multiline configs
|
||||
if option.action == 'append':
|
||||
val = val.split()
|
||||
else:
|
||||
option.nargs = 1
|
||||
if option.action in ('store_true', 'store_false', 'count'):
|
||||
val = strtobool(val)
|
||||
try:
|
||||
val = option.convert_value(key, val)
|
||||
except optparse.OptionValueError:
|
||||
e = sys.exc_info()[1]
|
||||
print("An error occured during configuration: %s" % e)
|
||||
sys.exit(3)
|
||||
defaults[option.dest] = val
|
||||
return defaults
|
||||
|
||||
def normalize_keys(self, items):
|
||||
"""Return a config dictionary with normalized keys regardless of
|
||||
whether the keys were specified in environment variables or in config
|
||||
files"""
|
||||
normalized = {}
|
||||
for key, val in items:
|
||||
key = key.replace('_', '-')
|
||||
if not key.startswith('--'):
|
||||
key = '--%s' % key # only prefer long opts
|
||||
normalized[key] = val
|
||||
return normalized
|
||||
|
||||
def get_config_section(self, name):
|
||||
"""Get a section of a configuration"""
|
||||
if self.config.has_section(name):
|
||||
return self.config.items(name)
|
||||
return []
|
||||
|
||||
def get_environ_vars(self, prefix='PIP_'):
|
||||
"""Returns a generator with all environmental vars with prefix PIP_"""
|
||||
for key, val in os.environ.items():
|
||||
if key.startswith(prefix):
|
||||
yield (key.replace(prefix, '').lower(), val)
|
||||
|
||||
def get_default_values(self):
|
||||
"""Overridding to make updating the defaults after instantiation of
|
||||
the option parser possible, update_defaults() does the dirty work."""
|
||||
if not self.process_default_values:
|
||||
# Old, pre-Optik 1.5 behaviour.
|
||||
return optparse.Values(self.defaults)
|
||||
|
||||
defaults = self.update_defaults(self.defaults.copy()) # ours
|
||||
for option in self._get_all_options():
|
||||
default = defaults.get(option.dest)
|
||||
if isinstance(default, string_types):
|
||||
opt_str = option.get_opt_string()
|
||||
defaults[option.dest] = option.check_value(opt_str, default)
|
||||
return optparse.Values(defaults)
|
||||
|
||||
try:
|
||||
pip_dist = pkg_resources.get_distribution('pip')
|
||||
version = '%s from %s (python %s)' % (
|
||||
pip_dist, pip_dist.location, sys.version[:3])
|
||||
except pkg_resources.DistributionNotFound:
|
||||
# when running pip.py without installing
|
||||
version=None
|
||||
|
||||
parser = ConfigOptionParser(
|
||||
usage='%prog COMMAND [OPTIONS]',
|
||||
version=version,
|
||||
add_help_option=False,
|
||||
formatter=UpdatingDefaultsHelpFormatter(),
|
||||
name='global')
|
||||
|
||||
parser.add_option(
|
||||
'-h', '--help',
|
||||
dest='help',
|
||||
action='store_true',
|
||||
help='Show help')
|
||||
parser.add_option(
|
||||
# Run only if inside a virtualenv, bail if not.
|
||||
'--require-virtualenv', '--require-venv',
|
||||
dest='require_venv',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
|
||||
parser.add_option(
|
||||
'-v', '--verbose',
|
||||
dest='verbose',
|
||||
action='count',
|
||||
default=0,
|
||||
help='Give more output')
|
||||
parser.add_option(
|
||||
'-q', '--quiet',
|
||||
dest='quiet',
|
||||
action='count',
|
||||
default=0,
|
||||
help='Give less output')
|
||||
parser.add_option(
|
||||
'--log',
|
||||
dest='log',
|
||||
metavar='FILENAME',
|
||||
help='Log file where a complete (maximum verbosity) record will be kept')
|
||||
parser.add_option(
|
||||
# Writes the log levels explicitely to the log'
|
||||
'--log-explicit-levels',
|
||||
dest='log_explicit_levels',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
parser.add_option(
|
||||
# The default log file
|
||||
'--local-log', '--log-file',
|
||||
dest='log_file',
|
||||
metavar='FILENAME',
|
||||
default=default_log_file,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
parser.add_option(
|
||||
# Don't ask for input
|
||||
'--no-input',
|
||||
dest='no_input',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
|
||||
parser.add_option(
|
||||
'--proxy',
|
||||
dest='proxy',
|
||||
type='str',
|
||||
default='',
|
||||
help="Specify a proxy in the form user:passwd@proxy.server:port. "
|
||||
"Note that the user:password@ is optional and required only if you "
|
||||
"are behind an authenticated proxy. If you provide "
|
||||
"user@proxy.server:port then you will be prompted for a password.")
|
||||
parser.add_option(
|
||||
'--timeout', '--default-timeout',
|
||||
metavar='SECONDS',
|
||||
dest='timeout',
|
||||
type='float',
|
||||
default=15,
|
||||
help='Set the socket timeout (default %default seconds)')
|
||||
parser.add_option(
|
||||
# The default version control system for editables, e.g. 'svn'
|
||||
'--default-vcs',
|
||||
dest='default_vcs',
|
||||
type='str',
|
||||
default='',
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
parser.add_option(
|
||||
# A regex to be used to skip requirements
|
||||
'--skip-requirements-regex',
|
||||
dest='skip_requirements_regex',
|
||||
type='str',
|
||||
default='',
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
|
||||
parser.add_option(
|
||||
# Option when path already exist
|
||||
'--exists-action',
|
||||
dest='exists_action',
|
||||
type='choice',
|
||||
choices=['s', 'i', 'w', 'b'],
|
||||
default=[],
|
||||
action='append',
|
||||
help="Default action when a path already exists."
|
||||
"Use this option more then one time to specify "
|
||||
"another action if a certain option is not "
|
||||
"available, choices: "
|
||||
"(s)witch, (i)gnore, (w)ipe, (b)ackup")
|
||||
|
||||
parser.disable_interspersed_args()
|
||||
-1
@@ -1 +0,0 @@
|
||||
#
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
from pip.basecommand import (Command, command_dict,
|
||||
load_all_commands, SUCCESS,
|
||||
ERROR)
|
||||
from pip.exceptions import CommandError
|
||||
from pip.baseparser import parser
|
||||
|
||||
|
||||
class HelpCommand(Command):
|
||||
name = 'help'
|
||||
usage = '%prog'
|
||||
summary = 'Show available commands'
|
||||
|
||||
def run(self, options, args):
|
||||
load_all_commands()
|
||||
if args:
|
||||
## FIXME: handle errors better here
|
||||
command = args[0]
|
||||
if command not in command_dict:
|
||||
raise CommandError('No command with the name: %s' % command)
|
||||
command = command_dict[command]
|
||||
command.parser.print_help()
|
||||
return SUCCESS
|
||||
parser.print_help()
|
||||
print('\nCommands available:')
|
||||
commands = list(set(command_dict.values()))
|
||||
commands.sort(key=lambda x: x.name)
|
||||
for command in commands:
|
||||
if command.hidden:
|
||||
continue
|
||||
print(' %s: %s' % (command.name, command.summary))
|
||||
return SUCCESS
|
||||
|
||||
HelpCommand()
|
||||
-279
@@ -1,279 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
from pip.req import InstallRequirement, RequirementSet
|
||||
from pip.req import parse_requirements
|
||||
from pip.log import logger
|
||||
from pip.locations import build_prefix, src_prefix
|
||||
from pip.basecommand import Command
|
||||
from pip.index import PackageFinder
|
||||
from pip.exceptions import InstallationError, CommandError
|
||||
|
||||
|
||||
class InstallCommand(Command):
|
||||
name = 'install'
|
||||
usage = '%prog [OPTIONS] PACKAGE_NAMES...'
|
||||
summary = 'Install packages'
|
||||
bundle = False
|
||||
|
||||
def __init__(self):
|
||||
super(InstallCommand, self).__init__()
|
||||
self.parser.add_option(
|
||||
'-e', '--editable',
|
||||
dest='editables',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='VCS+REPOS_URL[@REV]#egg=PACKAGE',
|
||||
help='Install a package directly from a checkout. Source will be checked '
|
||||
'out into src/PACKAGE (lower-case) and installed in-place (using '
|
||||
'setup.py develop). You can run this on an existing directory/checkout (like '
|
||||
'pip install -e src/mycheckout). This option may be provided multiple times. '
|
||||
'Possible values for VCS are: svn, git, hg and bzr.')
|
||||
self.parser.add_option(
|
||||
'-r', '--requirement',
|
||||
dest='requirements',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='FILENAME',
|
||||
help='Install all the packages listed in the given requirements file. '
|
||||
'This option can be used multiple times.')
|
||||
self.parser.add_option(
|
||||
'-f', '--find-links',
|
||||
dest='find_links',
|
||||
action='append',
|
||||
default=[],
|
||||
metavar='URL',
|
||||
help='URL to look for packages at')
|
||||
self.parser.add_option(
|
||||
'-i', '--index-url', '--pypi-url',
|
||||
dest='index_url',
|
||||
metavar='URL',
|
||||
default='http://pypi.python.org/simple/',
|
||||
help='Base URL of Python Package Index (default %default)')
|
||||
self.parser.add_option(
|
||||
'--extra-index-url',
|
||||
dest='extra_index_urls',
|
||||
metavar='URL',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Extra URLs of package indexes to use in addition to --index-url')
|
||||
self.parser.add_option(
|
||||
'--no-index',
|
||||
dest='no_index',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Ignore package index (only looking at --find-links URLs instead)')
|
||||
self.parser.add_option(
|
||||
'-M', '--use-mirrors',
|
||||
dest='use_mirrors',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Use the PyPI mirrors as a fallback in case the main index is down.')
|
||||
self.parser.add_option(
|
||||
'--mirrors',
|
||||
dest='mirrors',
|
||||
metavar='URL',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Specific mirror URLs to query when --use-mirrors is used')
|
||||
|
||||
self.parser.add_option(
|
||||
'-b', '--build', '--build-dir', '--build-directory',
|
||||
dest='build_dir',
|
||||
metavar='DIR',
|
||||
default=build_prefix,
|
||||
help='Unpack packages into DIR (default %default) and build from there')
|
||||
self.parser.add_option(
|
||||
'-t', '--target',
|
||||
dest='target_dir',
|
||||
metavar='DIR',
|
||||
default=None,
|
||||
help='Install packages into DIR.')
|
||||
self.parser.add_option(
|
||||
'-d', '--download', '--download-dir', '--download-directory',
|
||||
dest='download_dir',
|
||||
metavar='DIR',
|
||||
default=None,
|
||||
help='Download packages into DIR instead of installing them')
|
||||
self.parser.add_option(
|
||||
'--download-cache',
|
||||
dest='download_cache',
|
||||
metavar='DIR',
|
||||
default=None,
|
||||
help='Cache downloaded packages in DIR')
|
||||
self.parser.add_option(
|
||||
'--src', '--source', '--source-dir', '--source-directory',
|
||||
dest='src_dir',
|
||||
metavar='DIR',
|
||||
default=src_prefix,
|
||||
help='Check out --editable packages into DIR (default %default)')
|
||||
|
||||
self.parser.add_option(
|
||||
'-U', '--upgrade',
|
||||
dest='upgrade',
|
||||
action='store_true',
|
||||
help='Upgrade all packages to the newest available version')
|
||||
self.parser.add_option(
|
||||
'--force-reinstall',
|
||||
dest='force_reinstall',
|
||||
action='store_true',
|
||||
help='When upgrading, reinstall all packages even if they are '
|
||||
'already up-to-date.')
|
||||
self.parser.add_option(
|
||||
'-I', '--ignore-installed',
|
||||
dest='ignore_installed',
|
||||
action='store_true',
|
||||
help='Ignore the installed packages (reinstalling instead)')
|
||||
self.parser.add_option(
|
||||
'--no-deps', '--no-dependencies',
|
||||
dest='ignore_dependencies',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Ignore package dependencies')
|
||||
self.parser.add_option(
|
||||
'--no-install',
|
||||
dest='no_install',
|
||||
action='store_true',
|
||||
help="Download and unpack all packages, but don't actually install them")
|
||||
self.parser.add_option(
|
||||
'--no-download',
|
||||
dest='no_download',
|
||||
action="store_true",
|
||||
help="Don't download any packages, just install the ones already downloaded "
|
||||
"(completes an install run with --no-install)")
|
||||
|
||||
self.parser.add_option(
|
||||
'--install-option',
|
||||
dest='install_options',
|
||||
action='append',
|
||||
help="Extra arguments to be supplied to the setup.py install "
|
||||
"command (use like --install-option=\"--install-scripts=/usr/local/bin\"). "
|
||||
"Use multiple --install-option options to pass multiple options to setup.py install. "
|
||||
"If you are using an option with a directory path, be sure to use absolute path.")
|
||||
|
||||
self.parser.add_option(
|
||||
'--global-option',
|
||||
dest='global_options',
|
||||
action='append',
|
||||
help="Extra global options to be supplied to the setup.py"
|
||||
"call before the install command")
|
||||
|
||||
self.parser.add_option(
|
||||
'--user',
|
||||
dest='use_user_site',
|
||||
action='store_true',
|
||||
help='Install to user-site')
|
||||
|
||||
def _build_package_finder(self, options, index_urls):
|
||||
"""
|
||||
Create a package finder appropriate to this install command.
|
||||
This method is meant to be overridden by subclasses, not
|
||||
called directly.
|
||||
"""
|
||||
return PackageFinder(find_links=options.find_links,
|
||||
index_urls=index_urls,
|
||||
use_mirrors=options.use_mirrors,
|
||||
mirrors=options.mirrors)
|
||||
|
||||
def run(self, options, args):
|
||||
if options.download_dir:
|
||||
options.no_install = True
|
||||
options.ignore_installed = True
|
||||
options.build_dir = os.path.abspath(options.build_dir)
|
||||
options.src_dir = os.path.abspath(options.src_dir)
|
||||
install_options = options.install_options or []
|
||||
if options.use_user_site:
|
||||
install_options.append('--user')
|
||||
if options.target_dir:
|
||||
options.ignore_installed = True
|
||||
temp_target_dir = tempfile.mkdtemp()
|
||||
options.target_dir = os.path.abspath(options.target_dir)
|
||||
if os.path.exists(options.target_dir) and not os.path.isdir(options.target_dir):
|
||||
raise CommandError("Target path exists but is not a directory, will not continue.")
|
||||
install_options.append('--home=' + temp_target_dir)
|
||||
global_options = options.global_options or []
|
||||
index_urls = [options.index_url] + options.extra_index_urls
|
||||
if options.no_index:
|
||||
logger.notify('Ignoring indexes: %s' % ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
finder = self._build_package_finder(options, index_urls)
|
||||
|
||||
requirement_set = RequirementSet(
|
||||
build_dir=options.build_dir,
|
||||
src_dir=options.src_dir,
|
||||
download_dir=options.download_dir,
|
||||
download_cache=options.download_cache,
|
||||
upgrade=options.upgrade,
|
||||
ignore_installed=options.ignore_installed,
|
||||
ignore_dependencies=options.ignore_dependencies,
|
||||
force_reinstall=options.force_reinstall)
|
||||
for name in args:
|
||||
requirement_set.add_requirement(
|
||||
InstallRequirement.from_line(name, None))
|
||||
for name in options.editables:
|
||||
requirement_set.add_requirement(
|
||||
InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
|
||||
for filename in options.requirements:
|
||||
for req in parse_requirements(filename, finder=finder, options=options):
|
||||
requirement_set.add_requirement(req)
|
||||
if not requirement_set.has_requirements:
|
||||
opts = {'name': self.name}
|
||||
if options.find_links:
|
||||
msg = ('You must give at least one requirement to %(name)s '
|
||||
'(maybe you meant "pip %(name)s %(links)s"?)' %
|
||||
dict(opts, links=' '.join(options.find_links)))
|
||||
else:
|
||||
msg = ('You must give at least one requirement '
|
||||
'to %(name)s (see "pip help %(name)s")' % opts)
|
||||
logger.warn(msg)
|
||||
return
|
||||
|
||||
if (options.use_user_site and
|
||||
sys.version_info < (2, 6)):
|
||||
raise InstallationError('--user is only supported in Python version 2.6 and newer')
|
||||
|
||||
import setuptools
|
||||
if (options.use_user_site and
|
||||
requirement_set.has_editables and
|
||||
not getattr(setuptools, '_distribute', False)):
|
||||
|
||||
raise InstallationError('--user --editable not supported with setuptools, use distribute')
|
||||
|
||||
if not options.no_download:
|
||||
requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
|
||||
else:
|
||||
requirement_set.locate_files()
|
||||
|
||||
if not options.no_install and not self.bundle:
|
||||
requirement_set.install(install_options, global_options)
|
||||
installed = ' '.join([req.name for req in
|
||||
requirement_set.successfully_installed])
|
||||
if installed:
|
||||
logger.notify('Successfully installed %s' % installed)
|
||||
elif not self.bundle:
|
||||
downloaded = ' '.join([req.name for req in
|
||||
requirement_set.successfully_downloaded])
|
||||
if downloaded:
|
||||
logger.notify('Successfully downloaded %s' % downloaded)
|
||||
elif self.bundle:
|
||||
requirement_set.create_bundle(self.bundle_filename)
|
||||
logger.notify('Created bundle in %s' % self.bundle_filename)
|
||||
# Clean up
|
||||
if not options.no_install or options.download_dir:
|
||||
requirement_set.cleanup_files(bundle=self.bundle)
|
||||
if options.target_dir:
|
||||
if not os.path.exists(options.target_dir):
|
||||
os.makedirs(options.target_dir)
|
||||
lib_dir = os.path.join(temp_target_dir, "lib/python/")
|
||||
for item in os.listdir(lib_dir):
|
||||
shutil.move(
|
||||
os.path.join(lib_dir, item),
|
||||
os.path.join(options.target_dir, item)
|
||||
)
|
||||
shutil.rmtree(temp_target_dir)
|
||||
return requirement_set
|
||||
|
||||
|
||||
InstallCommand()
|
||||
Vendored
-481
@@ -1,481 +0,0 @@
|
||||
import cgi
|
||||
import getpass
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from pip.backwardcompat import (md5, copytree, xmlrpclib, urllib, urllib2,
|
||||
urlparse, string_types, HTTPError)
|
||||
from pip.exceptions import InstallationError
|
||||
from pip.util import (splitext, rmtree, format_size, display_path,
|
||||
backup_dir, ask, ask_path_exists, unpack_file,
|
||||
create_download_cache_folder, cache_download)
|
||||
from pip.vcs import vcs
|
||||
from pip.log import logger
|
||||
|
||||
|
||||
__all__ = ['xmlrpclib_transport', 'get_file_content', 'urlopen',
|
||||
'is_url', 'url_to_path', 'path_to_url', 'path_to_url2',
|
||||
'geturl', 'is_archive_file', 'unpack_vcs_link',
|
||||
'unpack_file_url', 'is_vcs_url', 'is_file_url', 'unpack_http_url']
|
||||
|
||||
|
||||
xmlrpclib_transport = xmlrpclib.Transport()
|
||||
|
||||
|
||||
def get_file_content(url, comes_from=None):
|
||||
"""Gets the content of a file; it may be a filename, file: URL, or
|
||||
http: URL. Returns (location, content)"""
|
||||
match = _scheme_re.search(url)
|
||||
if match:
|
||||
scheme = match.group(1).lower()
|
||||
if (scheme == 'file' and comes_from
|
||||
and comes_from.startswith('http')):
|
||||
raise InstallationError(
|
||||
'Requirements file %s references URL %s, which is local'
|
||||
% (comes_from, url))
|
||||
if scheme == 'file':
|
||||
path = url.split(':', 1)[1]
|
||||
path = path.replace('\\', '/')
|
||||
match = _url_slash_drive_re.match(path)
|
||||
if match:
|
||||
path = match.group(1) + ':' + path.split('|', 1)[1]
|
||||
path = urllib.unquote(path)
|
||||
if path.startswith('/'):
|
||||
path = '/' + path.lstrip('/')
|
||||
url = path
|
||||
else:
|
||||
## FIXME: catch some errors
|
||||
resp = urlopen(url)
|
||||
return geturl(resp), resp.read()
|
||||
try:
|
||||
f = open(url)
|
||||
content = f.read()
|
||||
except IOError:
|
||||
e = sys.exc_info()[1]
|
||||
raise InstallationError('Could not open requirements file: %s' % str(e))
|
||||
else:
|
||||
f.close()
|
||||
return url, content
|
||||
|
||||
|
||||
_scheme_re = re.compile(r'^(http|https|file):', re.I)
|
||||
_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I)
|
||||
|
||||
|
||||
class URLOpener(object):
|
||||
"""
|
||||
pip's own URL helper that adds HTTP auth and proxy support
|
||||
"""
|
||||
def __init__(self):
|
||||
self.passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
||||
|
||||
def __call__(self, url):
|
||||
"""
|
||||
If the given url contains auth info or if a normal request gets a 401
|
||||
response, an attempt is made to fetch the resource using basic HTTP
|
||||
auth.
|
||||
|
||||
"""
|
||||
url, username, password = self.extract_credentials(url)
|
||||
if username is None:
|
||||
try:
|
||||
response = urllib2.urlopen(self.get_request(url))
|
||||
except urllib2.HTTPError:
|
||||
e = sys.exc_info()[1]
|
||||
if e.code != 401:
|
||||
raise
|
||||
response = self.get_response(url)
|
||||
else:
|
||||
response = self.get_response(url, username, password)
|
||||
return response
|
||||
|
||||
def get_request(self, url):
|
||||
"""
|
||||
Wraps the URL to retrieve to protects against "creative"
|
||||
interpretation of the RFC: http://bugs.python.org/issue8732
|
||||
"""
|
||||
if isinstance(url, string_types):
|
||||
url = urllib2.Request(url, headers={'Accept-encoding': 'identity'})
|
||||
return url
|
||||
|
||||
def get_response(self, url, username=None, password=None):
|
||||
"""
|
||||
does the dirty work of actually getting the rsponse object using urllib2
|
||||
and its HTTP auth builtins.
|
||||
"""
|
||||
scheme, netloc, path, query, frag = urlparse.urlsplit(url)
|
||||
req = self.get_request(url)
|
||||
|
||||
stored_username, stored_password = self.passman.find_user_password(None, netloc)
|
||||
# see if we have a password stored
|
||||
if stored_username is None:
|
||||
if username is None and self.prompting:
|
||||
username = urllib.quote(raw_input('User for %s: ' % netloc))
|
||||
password = urllib.quote(getpass.getpass('Password: '))
|
||||
if username and password:
|
||||
self.passman.add_password(None, netloc, username, password)
|
||||
stored_username, stored_password = self.passman.find_user_password(None, netloc)
|
||||
authhandler = urllib2.HTTPBasicAuthHandler(self.passman)
|
||||
opener = urllib2.build_opener(authhandler)
|
||||
# FIXME: should catch a 401 and offer to let the user reenter credentials
|
||||
return opener.open(req)
|
||||
|
||||
def setup(self, proxystr='', prompting=True):
|
||||
"""
|
||||
Sets the proxy handler given the option passed on the command
|
||||
line. If an empty string is passed it looks at the HTTP_PROXY
|
||||
environment variable.
|
||||
"""
|
||||
self.prompting = prompting
|
||||
proxy = self.get_proxy(proxystr)
|
||||
if proxy:
|
||||
proxy_support = urllib2.ProxyHandler({"http": proxy, "ftp": proxy, "https": proxy})
|
||||
opener = urllib2.build_opener(proxy_support, urllib2.CacheFTPHandler)
|
||||
urllib2.install_opener(opener)
|
||||
|
||||
def parse_credentials(self, netloc):
|
||||
if "@" in netloc:
|
||||
userinfo = netloc.rsplit("@", 1)[0]
|
||||
if ":" in userinfo:
|
||||
return userinfo.split(":", 1)
|
||||
return userinfo, None
|
||||
return None, None
|
||||
|
||||
def extract_credentials(self, url):
|
||||
"""
|
||||
Extracts user/password from a url.
|
||||
|
||||
Returns a tuple:
|
||||
(url-without-auth, username, password)
|
||||
"""
|
||||
if isinstance(url, urllib2.Request):
|
||||
result = urlparse.urlsplit(url.get_full_url())
|
||||
else:
|
||||
result = urlparse.urlsplit(url)
|
||||
scheme, netloc, path, query, frag = result
|
||||
|
||||
username, password = self.parse_credentials(netloc)
|
||||
if username is None:
|
||||
return url, None, None
|
||||
elif password is None and self.prompting:
|
||||
# remove the auth credentials from the url part
|
||||
netloc = netloc.replace('%s@' % username, '', 1)
|
||||
# prompt for the password
|
||||
prompt = 'Password for %s@%s: ' % (username, netloc)
|
||||
password = urllib.quote(getpass.getpass(prompt))
|
||||
else:
|
||||
# remove the auth credentials from the url part
|
||||
netloc = netloc.replace('%s:%s@' % (username, password), '', 1)
|
||||
|
||||
target_url = urlparse.urlunsplit((scheme, netloc, path, query, frag))
|
||||
return target_url, username, password
|
||||
|
||||
def get_proxy(self, proxystr=''):
|
||||
"""
|
||||
Get the proxy given the option passed on the command line.
|
||||
If an empty string is passed it looks at the HTTP_PROXY
|
||||
environment variable.
|
||||
"""
|
||||
if not proxystr:
|
||||
proxystr = os.environ.get('HTTP_PROXY', '')
|
||||
if proxystr:
|
||||
if '@' in proxystr:
|
||||
user_password, server_port = proxystr.split('@', 1)
|
||||
if ':' in user_password:
|
||||
user, password = user_password.split(':', 1)
|
||||
else:
|
||||
user = user_password
|
||||
prompt = 'Password for %s@%s: ' % (user, server_port)
|
||||
password = urllib.quote(getpass.getpass(prompt))
|
||||
return '%s:%s@%s' % (user, password, server_port)
|
||||
else:
|
||||
return proxystr
|
||||
else:
|
||||
return None
|
||||
|
||||
urlopen = URLOpener()
|
||||
|
||||
|
||||
def is_url(name):
|
||||
"""Returns true if the name looks like a URL"""
|
||||
if ':' not in name:
|
||||
return False
|
||||
scheme = name.split(':', 1)[0].lower()
|
||||
return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes
|
||||
|
||||
|
||||
def url_to_path(url):
|
||||
"""
|
||||
Convert a file: URL to a path.
|
||||
"""
|
||||
assert url.startswith('file:'), (
|
||||
"You can only turn file: urls into filenames (not %r)" % url)
|
||||
path = url[len('file:'):].lstrip('/')
|
||||
path = urllib.unquote(path)
|
||||
if _url_drive_re.match(path):
|
||||
path = path[0] + ':' + path[2:]
|
||||
else:
|
||||
path = '/' + path
|
||||
return path
|
||||
|
||||
|
||||
_drive_re = re.compile('^([a-z]):', re.I)
|
||||
_url_drive_re = re.compile('^([a-z])[:|]', re.I)
|
||||
|
||||
|
||||
def path_to_url(path):
|
||||
"""
|
||||
Convert a path to a file: URL. The path will be made absolute.
|
||||
"""
|
||||
path = os.path.normcase(os.path.abspath(path))
|
||||
if _drive_re.match(path):
|
||||
path = path[0] + '|' + path[2:]
|
||||
url = urllib.quote(path)
|
||||
url = url.replace(os.path.sep, '/')
|
||||
url = url.lstrip('/')
|
||||
return 'file:///' + url
|
||||
|
||||
|
||||
def path_to_url2(path):
|
||||
"""
|
||||
Convert a path to a file: URL. The path will be made absolute and have
|
||||
quoted path parts.
|
||||
"""
|
||||
path = os.path.normpath(os.path.abspath(path))
|
||||
drive, path = os.path.splitdrive(path)
|
||||
filepath = path.split(os.path.sep)
|
||||
url = '/'.join([urllib.quote(part) for part in filepath])
|
||||
if not drive:
|
||||
url = url.lstrip('/')
|
||||
return 'file:///' + drive + url
|
||||
|
||||
|
||||
def geturl(urllib2_resp):
|
||||
"""
|
||||
Use instead of urllib.addinfourl.geturl(), which appears to have
|
||||
some issues with dropping the double slash for certain schemes
|
||||
(e.g. file://). This implementation is probably over-eager, as it
|
||||
always restores '://' if it is missing, and it appears some url
|
||||
schemata aren't always followed by '//' after the colon, but as
|
||||
far as I know pip doesn't need any of those.
|
||||
The URI RFC can be found at: http://tools.ietf.org/html/rfc1630
|
||||
|
||||
This function assumes that
|
||||
scheme:/foo/bar
|
||||
is the same as
|
||||
scheme:///foo/bar
|
||||
"""
|
||||
url = urllib2_resp.geturl()
|
||||
scheme, rest = url.split(':', 1)
|
||||
if rest.startswith('//'):
|
||||
return url
|
||||
else:
|
||||
# FIXME: write a good test to cover it
|
||||
return '%s://%s' % (scheme, rest)
|
||||
|
||||
|
||||
def is_archive_file(name):
|
||||
"""Return True if `name` is a considered as an archive file."""
|
||||
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar', '.pybundle')
|
||||
ext = splitext(name)[1].lower()
|
||||
if ext in archives:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def unpack_vcs_link(link, location, only_download=False):
|
||||
vcs_backend = _get_used_vcs_backend(link)
|
||||
if only_download:
|
||||
vcs_backend.export(location)
|
||||
else:
|
||||
vcs_backend.unpack(location)
|
||||
|
||||
|
||||
def unpack_file_url(link, location):
|
||||
source = url_to_path(link.url)
|
||||
content_type = mimetypes.guess_type(source)[0]
|
||||
if os.path.isdir(source):
|
||||
# delete the location since shutil will create it again :(
|
||||
if os.path.isdir(location):
|
||||
rmtree(location)
|
||||
copytree(source, location)
|
||||
else:
|
||||
unpack_file(source, location, content_type, link)
|
||||
|
||||
|
||||
def _get_used_vcs_backend(link):
|
||||
for backend in vcs.backends:
|
||||
if link.scheme in backend.schemes:
|
||||
vcs_backend = backend(link.url)
|
||||
return vcs_backend
|
||||
|
||||
|
||||
def is_vcs_url(link):
|
||||
return bool(_get_used_vcs_backend(link))
|
||||
|
||||
|
||||
def is_file_url(link):
|
||||
return link.url.lower().startswith('file:')
|
||||
|
||||
|
||||
def _check_md5(download_hash, link):
|
||||
download_hash = download_hash.hexdigest()
|
||||
if download_hash != link.md5_hash:
|
||||
logger.fatal("MD5 hash of the package %s (%s) doesn't match the expected hash %s!"
|
||||
% (link, download_hash, link.md5_hash))
|
||||
raise InstallationError('Bad MD5 hash for package %s' % link)
|
||||
|
||||
|
||||
def _get_md5_from_file(target_file, link):
|
||||
download_hash = md5()
|
||||
fp = open(target_file, 'rb')
|
||||
while True:
|
||||
chunk = fp.read(4096)
|
||||
if not chunk:
|
||||
break
|
||||
download_hash.update(chunk)
|
||||
fp.close()
|
||||
return download_hash
|
||||
|
||||
|
||||
def _download_url(resp, link, temp_location):
|
||||
fp = open(temp_location, 'wb')
|
||||
download_hash = None
|
||||
if link.md5_hash:
|
||||
download_hash = md5()
|
||||
try:
|
||||
total_length = int(resp.info()['content-length'])
|
||||
except (ValueError, KeyError, TypeError):
|
||||
total_length = 0
|
||||
downloaded = 0
|
||||
show_progress = total_length > 40*1000 or not total_length
|
||||
show_url = link.show_url
|
||||
try:
|
||||
if show_progress:
|
||||
## FIXME: the URL can get really long in this message:
|
||||
if total_length:
|
||||
logger.start_progress('Downloading %s (%s): ' % (show_url, format_size(total_length)))
|
||||
else:
|
||||
logger.start_progress('Downloading %s (unknown size): ' % show_url)
|
||||
else:
|
||||
logger.notify('Downloading %s' % show_url)
|
||||
logger.debug('Downloading from URL %s' % link)
|
||||
|
||||
while True:
|
||||
chunk = resp.read(4096)
|
||||
if not chunk:
|
||||
break
|
||||
downloaded += len(chunk)
|
||||
if show_progress:
|
||||
if not total_length:
|
||||
logger.show_progress('%s' % format_size(downloaded))
|
||||
else:
|
||||
logger.show_progress('%3i%% %s' % (100*downloaded/total_length, format_size(downloaded)))
|
||||
if link.md5_hash:
|
||||
download_hash.update(chunk)
|
||||
fp.write(chunk)
|
||||
fp.close()
|
||||
finally:
|
||||
if show_progress:
|
||||
logger.end_progress('%s downloaded' % format_size(downloaded))
|
||||
return download_hash
|
||||
|
||||
|
||||
def _copy_file(filename, location, content_type, link):
|
||||
copy = True
|
||||
download_location = os.path.join(location, link.filename)
|
||||
if os.path.exists(download_location):
|
||||
response = ask_path_exists(
|
||||
'The file %s exists. (i)gnore, (w)ipe, (b)ackup ' %
|
||||
display_path(download_location), ('i', 'w', 'b'))
|
||||
if response == 'i':
|
||||
copy = False
|
||||
elif response == 'w':
|
||||
logger.warn('Deleting %s' % display_path(download_location))
|
||||
os.remove(download_location)
|
||||
elif response == 'b':
|
||||
dest_file = backup_dir(download_location)
|
||||
logger.warn('Backing up %s to %s'
|
||||
% (display_path(download_location), display_path(dest_file)))
|
||||
shutil.move(download_location, dest_file)
|
||||
if copy:
|
||||
shutil.copy(filename, download_location)
|
||||
logger.indent -= 2
|
||||
logger.notify('Saved %s' % display_path(download_location))
|
||||
|
||||
|
||||
def unpack_http_url(link, location, download_cache, download_dir=None):
|
||||
temp_dir = tempfile.mkdtemp('-unpack', 'pip-')
|
||||
target_url = link.url.split('#', 1)[0]
|
||||
target_file = None
|
||||
download_hash = None
|
||||
if download_cache:
|
||||
target_file = os.path.join(download_cache,
|
||||
urllib.quote(target_url, ''))
|
||||
if not os.path.isdir(download_cache):
|
||||
create_download_cache_folder(download_cache)
|
||||
if (target_file
|
||||
and os.path.exists(target_file)
|
||||
and os.path.exists(target_file + '.content-type')):
|
||||
fp = open(target_file+'.content-type')
|
||||
content_type = fp.read().strip()
|
||||
fp.close()
|
||||
if link.md5_hash:
|
||||
download_hash = _get_md5_from_file(target_file, link)
|
||||
temp_location = target_file
|
||||
logger.notify('Using download cache from %s' % target_file)
|
||||
else:
|
||||
resp = _get_response_from_url(target_url, link)
|
||||
content_type = resp.info()['content-type']
|
||||
filename = link.filename # fallback
|
||||
# Have a look at the Content-Disposition header for a better guess
|
||||
content_disposition = resp.info().get('content-disposition')
|
||||
if content_disposition:
|
||||
type, params = cgi.parse_header(content_disposition)
|
||||
# We use ``or`` here because we don't want to use an "empty" value
|
||||
# from the filename param.
|
||||
filename = params.get('filename') or filename
|
||||
ext = splitext(filename)[1]
|
||||
if not ext:
|
||||
ext = mimetypes.guess_extension(content_type)
|
||||
if ext:
|
||||
filename += ext
|
||||
if not ext and link.url != geturl(resp):
|
||||
ext = os.path.splitext(geturl(resp))[1]
|
||||
if ext:
|
||||
filename += ext
|
||||
temp_location = os.path.join(temp_dir, filename)
|
||||
download_hash = _download_url(resp, link, temp_location)
|
||||
if link.md5_hash:
|
||||
_check_md5(download_hash, link)
|
||||
if download_dir:
|
||||
_copy_file(temp_location, download_dir, content_type, link)
|
||||
unpack_file(temp_location, location, content_type, link)
|
||||
if target_file and target_file != temp_location:
|
||||
cache_download(target_file, temp_location, content_type)
|
||||
if target_file is None:
|
||||
os.unlink(temp_location)
|
||||
os.rmdir(temp_dir)
|
||||
|
||||
|
||||
def _get_response_from_url(target_url, link):
|
||||
try:
|
||||
resp = urlopen(target_url)
|
||||
except urllib2.HTTPError:
|
||||
e = sys.exc_info()[1]
|
||||
logger.fatal("HTTP error %s while getting %s" % (e.code, link))
|
||||
raise
|
||||
except IOError:
|
||||
e = sys.exc_info()[1]
|
||||
# Typically an FTP error
|
||||
logger.fatal("Error %s while getting %s" % (e, link))
|
||||
raise
|
||||
return resp
|
||||
|
||||
|
||||
class Urllib2HeadRequest(urllib2.Request):
|
||||
def get_method(self):
|
||||
return "HEAD"
|
||||
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
"""Exceptions used throughout package"""
|
||||
|
||||
|
||||
class InstallationError(Exception):
|
||||
"""General exception during installation"""
|
||||
|
||||
|
||||
class UninstallationError(Exception):
|
||||
"""General exception during uninstallation"""
|
||||
|
||||
|
||||
class DistributionNotFound(InstallationError):
|
||||
"""Raised when a distribution cannot be found to satisfy a requirement"""
|
||||
|
||||
|
||||
class BestVersionAlreadyInstalled(Exception):
|
||||
"""Raised when the most up-to-date version of a package is already
|
||||
installed.
|
||||
"""
|
||||
|
||||
|
||||
class BadCommand(Exception):
|
||||
"""Raised when virtualenv or a command is not found"""
|
||||
|
||||
|
||||
class CommandError(Exception):
|
||||
"""Raised when there is an error in command-line arguments"""
|
||||
Vendored
-708
@@ -1,708 +0,0 @@
|
||||
"""Routines related to PyPI, indexes"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import gzip
|
||||
import mimetypes
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
import dummy_threading as threading
|
||||
import posixpath
|
||||
import pkg_resources
|
||||
import random
|
||||
import socket
|
||||
import string
|
||||
import zlib
|
||||
from pip.log import logger
|
||||
from pip.util import Inf
|
||||
from pip.util import normalize_name, splitext
|
||||
from pip.exceptions import DistributionNotFound, BestVersionAlreadyInstalled
|
||||
from pip.backwardcompat import (WindowsError, BytesIO,
|
||||
Queue, httplib, urlparse,
|
||||
URLError, HTTPError, u,
|
||||
product, url2pathname)
|
||||
from pip.backwardcompat import Empty as QueueEmpty
|
||||
from pip.download import urlopen, path_to_url2, url_to_path, geturl, Urllib2HeadRequest
|
||||
|
||||
__all__ = ['PackageFinder']
|
||||
|
||||
|
||||
DEFAULT_MIRROR_URL = "last.pypi.python.org"
|
||||
|
||||
|
||||
class PackageFinder(object):
|
||||
"""This finds packages.
|
||||
|
||||
This is meant to match easy_install's technique for looking for
|
||||
packages, by reading pages and looking for appropriate links
|
||||
"""
|
||||
|
||||
def __init__(self, find_links, index_urls,
|
||||
use_mirrors=False, mirrors=None, main_mirror_url=None):
|
||||
self.find_links = find_links
|
||||
self.index_urls = index_urls
|
||||
self.dependency_links = []
|
||||
self.cache = PageCache()
|
||||
# These are boring links that have already been logged somehow:
|
||||
self.logged_links = set()
|
||||
if use_mirrors:
|
||||
self.mirror_urls = self._get_mirror_urls(mirrors, main_mirror_url)
|
||||
logger.info('Using PyPI mirrors: %s' % ', '.join(self.mirror_urls))
|
||||
else:
|
||||
self.mirror_urls = []
|
||||
|
||||
def add_dependency_links(self, links):
|
||||
## FIXME: this shouldn't be global list this, it should only
|
||||
## apply to requirements of the package that specifies the
|
||||
## dependency_links value
|
||||
## FIXME: also, we should track comes_from (i.e., use Link)
|
||||
self.dependency_links.extend(links)
|
||||
|
||||
@staticmethod
|
||||
def _sort_locations(locations):
|
||||
"""
|
||||
Sort locations into "files" (archives) and "urls", and return
|
||||
a pair of lists (files,urls)
|
||||
"""
|
||||
files = []
|
||||
urls = []
|
||||
|
||||
# puts the url for the given file path into the appropriate
|
||||
# list
|
||||
def sort_path(path):
|
||||
url = path_to_url2(path)
|
||||
if mimetypes.guess_type(url, strict=False)[0] == 'text/html':
|
||||
urls.append(url)
|
||||
else:
|
||||
files.append(url)
|
||||
|
||||
for url in locations:
|
||||
if url.startswith('file:'):
|
||||
path = url_to_path(url)
|
||||
if os.path.isdir(path):
|
||||
path = os.path.realpath(path)
|
||||
for item in os.listdir(path):
|
||||
sort_path(os.path.join(path, item))
|
||||
elif os.path.isfile(path):
|
||||
sort_path(path)
|
||||
else:
|
||||
urls.append(url)
|
||||
return files, urls
|
||||
|
||||
def find_requirement(self, req, upgrade):
|
||||
url_name = req.url_name
|
||||
# Only check main index if index URL is given:
|
||||
main_index_url = None
|
||||
if self.index_urls:
|
||||
# Check that we have the url_name correctly spelled:
|
||||
main_index_url = Link(posixpath.join(self.index_urls[0], url_name))
|
||||
# This will also cache the page, so it's okay that we get it again later:
|
||||
page = self._get_page(main_index_url, req)
|
||||
if page is None:
|
||||
url_name = self._find_url_name(Link(self.index_urls[0]), url_name, req) or req.url_name
|
||||
|
||||
# Combine index URLs with mirror URLs here to allow
|
||||
# adding more index URLs from requirements files
|
||||
all_index_urls = self.index_urls + self.mirror_urls
|
||||
|
||||
def mkurl_pypi_url(url):
|
||||
loc = posixpath.join(url, url_name)
|
||||
# For maximum compatibility with easy_install, ensure the path
|
||||
# ends in a trailing slash. Although this isn't in the spec
|
||||
# (and PyPI can handle it without the slash) some other index
|
||||
# implementations might break if they relied on easy_install's behavior.
|
||||
if not loc.endswith('/'):
|
||||
loc = loc + '/'
|
||||
return loc
|
||||
if url_name is not None:
|
||||
locations = [
|
||||
mkurl_pypi_url(url)
|
||||
for url in all_index_urls] + self.find_links
|
||||
else:
|
||||
locations = list(self.find_links)
|
||||
locations.extend(self.dependency_links)
|
||||
for version in req.absolute_versions:
|
||||
if url_name is not None and main_index_url is not None:
|
||||
locations = [
|
||||
posixpath.join(main_index_url.url, version)] + locations
|
||||
|
||||
file_locations, url_locations = self._sort_locations(locations)
|
||||
|
||||
locations = [Link(url) for url in url_locations]
|
||||
logger.debug('URLs to search for versions for %s:' % req)
|
||||
for location in locations:
|
||||
logger.debug('* %s' % location)
|
||||
found_versions = []
|
||||
found_versions.extend(
|
||||
self._package_versions(
|
||||
[Link(url, '-f') for url in self.find_links], req.name.lower()))
|
||||
page_versions = []
|
||||
for page in self._get_pages(locations, req):
|
||||
logger.debug('Analyzing links from page %s' % page.url)
|
||||
logger.indent += 2
|
||||
try:
|
||||
page_versions.extend(self._package_versions(page.links, req.name.lower()))
|
||||
finally:
|
||||
logger.indent -= 2
|
||||
dependency_versions = list(self._package_versions(
|
||||
[Link(url) for url in self.dependency_links], req.name.lower()))
|
||||
if dependency_versions:
|
||||
logger.info('dependency_links found: %s' % ', '.join([link.url for parsed, link, version in dependency_versions]))
|
||||
file_versions = list(self._package_versions(
|
||||
[Link(url) for url in file_locations], req.name.lower()))
|
||||
if not found_versions and not page_versions and not dependency_versions and not file_versions:
|
||||
logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
|
||||
raise DistributionNotFound('No distributions at all found for %s' % req)
|
||||
if req.satisfied_by is not None:
|
||||
found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
|
||||
if file_versions:
|
||||
file_versions.sort(reverse=True)
|
||||
logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
|
||||
found_versions = file_versions + found_versions
|
||||
all_versions = found_versions + page_versions + dependency_versions
|
||||
applicable_versions = []
|
||||
for (parsed_version, link, version) in all_versions:
|
||||
if version not in req.req:
|
||||
logger.info("Ignoring link %s, version %s doesn't match %s"
|
||||
% (link, version, ','.join([''.join(s) for s in req.req.specs])))
|
||||
continue
|
||||
applicable_versions.append((link, version))
|
||||
applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
|
||||
existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
|
||||
if not upgrade and existing_applicable:
|
||||
if applicable_versions[0][1] is Inf:
|
||||
logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
|
||||
% req.satisfied_by.version)
|
||||
raise BestVersionAlreadyInstalled
|
||||
else:
|
||||
logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
|
||||
% (req.satisfied_by.version, applicable_versions[0][1]))
|
||||
return None
|
||||
if not applicable_versions:
|
||||
logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
|
||||
% (req, ', '.join([version for parsed_version, link, version in found_versions])))
|
||||
raise DistributionNotFound('No distributions matching the version for %s' % req)
|
||||
if applicable_versions[0][0] is Inf:
|
||||
# We have an existing version, and its the best version
|
||||
logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
|
||||
% (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
|
||||
raise BestVersionAlreadyInstalled
|
||||
if len(applicable_versions) > 1:
|
||||
logger.info('Using version %s (newest of versions: %s)' %
|
||||
(applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
|
||||
return applicable_versions[0][0]
|
||||
|
||||
def _find_url_name(self, index_url, url_name, req):
|
||||
"""Finds the true URL name of a package, when the given name isn't quite correct.
|
||||
This is usually used to implement case-insensitivity."""
|
||||
if not index_url.url.endswith('/'):
|
||||
# Vaguely part of the PyPI API... weird but true.
|
||||
## FIXME: bad to modify this?
|
||||
index_url.url += '/'
|
||||
page = self._get_page(index_url, req)
|
||||
if page is None:
|
||||
logger.fatal('Cannot fetch index base URL %s' % index_url)
|
||||
return
|
||||
norm_name = normalize_name(req.url_name)
|
||||
for link in page.links:
|
||||
base = posixpath.basename(link.path.rstrip('/'))
|
||||
if norm_name == normalize_name(base):
|
||||
logger.notify('Real name of requirement %s is %s' % (url_name, base))
|
||||
return base
|
||||
return None
|
||||
|
||||
def _get_pages(self, locations, req):
|
||||
"""Yields (page, page_url) from the given locations, skipping
|
||||
locations that have errors, and adding download/homepage links"""
|
||||
pending_queue = Queue()
|
||||
for location in locations:
|
||||
pending_queue.put(location)
|
||||
done = []
|
||||
seen = set()
|
||||
threads = []
|
||||
for i in range(min(10, len(locations))):
|
||||
t = threading.Thread(target=self._get_queued_page, args=(req, pending_queue, done, seen))
|
||||
t.setDaemon(True)
|
||||
threads.append(t)
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
return done
|
||||
|
||||
_log_lock = threading.Lock()
|
||||
|
||||
def _get_queued_page(self, req, pending_queue, done, seen):
|
||||
while 1:
|
||||
try:
|
||||
location = pending_queue.get(False)
|
||||
except QueueEmpty:
|
||||
return
|
||||
if location in seen:
|
||||
continue
|
||||
seen.add(location)
|
||||
page = self._get_page(location, req)
|
||||
if page is None:
|
||||
continue
|
||||
done.append(page)
|
||||
for link in page.rel_links():
|
||||
pending_queue.put(link)
|
||||
|
||||
_egg_fragment_re = re.compile(r'#egg=([^&]*)')
|
||||
_egg_info_re = re.compile(r'([a-z0-9_.]+)-([a-z0-9_.-]+)', re.I)
|
||||
_py_version_re = re.compile(r'-py([123]\.?[0-9]?)$')
|
||||
|
||||
def _sort_links(self, links):
|
||||
"Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates"
|
||||
eggs, no_eggs = [], []
|
||||
seen = set()
|
||||
for link in links:
|
||||
if link not in seen:
|
||||
seen.add(link)
|
||||
if link.egg_fragment:
|
||||
eggs.append(link)
|
||||
else:
|
||||
no_eggs.append(link)
|
||||
return no_eggs + eggs
|
||||
|
||||
def _package_versions(self, links, search_name):
|
||||
for link in self._sort_links(links):
|
||||
for v in self._link_package_versions(link, search_name):
|
||||
yield v
|
||||
|
||||
def _link_package_versions(self, link, search_name):
|
||||
"""
|
||||
Return an iterable of triples (pkg_resources_version_key,
|
||||
link, python_version) that can be extracted from the given
|
||||
link.
|
||||
|
||||
Meant to be overridden by subclasses, not called by clients.
|
||||
"""
|
||||
if link.egg_fragment:
|
||||
egg_info = link.egg_fragment
|
||||
else:
|
||||
egg_info, ext = link.splitext()
|
||||
if not ext:
|
||||
if link not in self.logged_links:
|
||||
logger.debug('Skipping link %s; not a file' % link)
|
||||
self.logged_links.add(link)
|
||||
return []
|
||||
if egg_info.endswith('.tar'):
|
||||
# Special double-extension case:
|
||||
egg_info = egg_info[:-4]
|
||||
ext = '.tar' + ext
|
||||
if ext not in ('.tar.gz', '.tar.bz2', '.tar', '.tgz', '.zip'):
|
||||
if link not in self.logged_links:
|
||||
logger.debug('Skipping link %s; unknown archive format: %s' % (link, ext))
|
||||
self.logged_links.add(link)
|
||||
return []
|
||||
if "macosx10" in link.path and ext == '.zip':
|
||||
if link not in self.logged_links:
|
||||
logger.debug('Skipping link %s; macosx10 one' % (link))
|
||||
self.logged_links.add(link)
|
||||
return []
|
||||
version = self._egg_info_matches(egg_info, search_name, link)
|
||||
if version is None:
|
||||
logger.debug('Skipping link %s; wrong project name (not %s)' % (link, search_name))
|
||||
return []
|
||||
match = self._py_version_re.search(version)
|
||||
if match:
|
||||
version = version[:match.start()]
|
||||
py_version = match.group(1)
|
||||
if py_version != sys.version[:3]:
|
||||
logger.debug('Skipping %s because Python version is incorrect' % link)
|
||||
return []
|
||||
logger.debug('Found link %s, version: %s' % (link, version))
|
||||
return [(pkg_resources.parse_version(version),
|
||||
link,
|
||||
version)]
|
||||
|
||||
def _egg_info_matches(self, egg_info, search_name, link):
|
||||
match = self._egg_info_re.search(egg_info)
|
||||
if not match:
|
||||
logger.debug('Could not parse version from link: %s' % link)
|
||||
return None
|
||||
name = match.group(0).lower()
|
||||
# To match the "safe" name that pkg_resources creates:
|
||||
name = name.replace('_', '-')
|
||||
if name.startswith(search_name.lower()):
|
||||
return match.group(0)[len(search_name):].lstrip('-')
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_page(self, link, req):
|
||||
return HTMLPage.get_page(link, req, cache=self.cache)
|
||||
|
||||
def _get_mirror_urls(self, mirrors=None, main_mirror_url=None):
|
||||
"""Retrieves a list of URLs from the main mirror DNS entry
|
||||
unless a list of mirror URLs are passed.
|
||||
"""
|
||||
if not mirrors:
|
||||
mirrors = get_mirrors(main_mirror_url)
|
||||
# Should this be made "less random"? E.g. netselect like?
|
||||
random.shuffle(mirrors)
|
||||
|
||||
mirror_urls = set()
|
||||
for mirror_url in mirrors:
|
||||
# Make sure we have a valid URL
|
||||
if not ("http://" or "https://" or "file://") in mirror_url:
|
||||
mirror_url = "http://%s" % mirror_url
|
||||
if not mirror_url.endswith("/simple"):
|
||||
mirror_url = "%s/simple/" % mirror_url
|
||||
mirror_urls.add(mirror_url)
|
||||
|
||||
return list(mirror_urls)
|
||||
|
||||
|
||||
class PageCache(object):
|
||||
"""Cache of HTML pages"""
|
||||
|
||||
failure_limit = 3
|
||||
|
||||
def __init__(self):
|
||||
self._failures = {}
|
||||
self._pages = {}
|
||||
self._archives = {}
|
||||
|
||||
def too_many_failures(self, url):
|
||||
return self._failures.get(url, 0) >= self.failure_limit
|
||||
|
||||
def get_page(self, url):
|
||||
return self._pages.get(url)
|
||||
|
||||
def is_archive(self, url):
|
||||
return self._archives.get(url, False)
|
||||
|
||||
def set_is_archive(self, url, value=True):
|
||||
self._archives[url] = value
|
||||
|
||||
def add_page_failure(self, url, level):
|
||||
self._failures[url] = self._failures.get(url, 0)+level
|
||||
|
||||
def add_page(self, urls, page):
|
||||
for url in urls:
|
||||
self._pages[url] = page
|
||||
|
||||
|
||||
class HTMLPage(object):
|
||||
"""Represents one page, along with its URL"""
|
||||
|
||||
## FIXME: these regexes are horrible hacks:
|
||||
_homepage_re = re.compile(r'<th>\s*home\s*page', re.I)
|
||||
_download_re = re.compile(r'<th>\s*download\s+url', re.I)
|
||||
## These aren't so aweful:
|
||||
_rel_re = re.compile("""<[^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*>""", re.I)
|
||||
_href_re = re.compile('href=(?:"([^"]*)"|\'([^\']*)\'|([^>\\s\\n]*))', re.I|re.S)
|
||||
_base_re = re.compile(r"""<base\s+href\s*=\s*['"]?([^'">]+)""", re.I)
|
||||
|
||||
def __init__(self, content, url, headers=None):
|
||||
self.content = content
|
||||
self.url = url
|
||||
self.headers = headers
|
||||
|
||||
def __str__(self):
|
||||
return self.url
|
||||
|
||||
@classmethod
|
||||
def get_page(cls, link, req, cache=None, skip_archives=True):
|
||||
url = link.url
|
||||
url = url.split('#', 1)[0]
|
||||
if cache.too_many_failures(url):
|
||||
return None
|
||||
|
||||
# Check for VCS schemes that do not support lookup as web pages.
|
||||
from pip.vcs import VcsSupport
|
||||
for scheme in VcsSupport.schemes:
|
||||
if url.lower().startswith(scheme) and url[len(scheme)] in '+:':
|
||||
logger.debug('Cannot look at %(scheme)s URL %(link)s' % locals())
|
||||
return None
|
||||
|
||||
if cache is not None:
|
||||
inst = cache.get_page(url)
|
||||
if inst is not None:
|
||||
return inst
|
||||
try:
|
||||
if skip_archives:
|
||||
if cache is not None:
|
||||
if cache.is_archive(url):
|
||||
return None
|
||||
filename = link.filename
|
||||
for bad_ext in ['.tar', '.tar.gz', '.tar.bz2', '.tgz', '.zip']:
|
||||
if filename.endswith(bad_ext):
|
||||
content_type = cls._get_content_type(url)
|
||||
if content_type.lower().startswith('text/html'):
|
||||
break
|
||||
else:
|
||||
logger.debug('Skipping page %s because of Content-Type: %s' % (link, content_type))
|
||||
if cache is not None:
|
||||
cache.set_is_archive(url)
|
||||
return None
|
||||
logger.debug('Getting page %s' % url)
|
||||
|
||||
# Tack index.html onto file:// URLs that point to directories
|
||||
(scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
|
||||
if scheme == 'file' and os.path.isdir(url2pathname(path)):
|
||||
# add trailing slash if not present so urljoin doesn't trim final segment
|
||||
if not url.endswith('/'):
|
||||
url += '/'
|
||||
url = urlparse.urljoin(url, 'index.html')
|
||||
logger.debug(' file: URL is directory, getting %s' % url)
|
||||
|
||||
resp = urlopen(url)
|
||||
|
||||
real_url = geturl(resp)
|
||||
headers = resp.info()
|
||||
contents = resp.read()
|
||||
encoding = headers.get('Content-Encoding', None)
|
||||
#XXX need to handle exceptions and add testing for this
|
||||
if encoding is not None:
|
||||
if encoding == 'gzip':
|
||||
contents = gzip.GzipFile(fileobj=BytesIO(contents)).read()
|
||||
if encoding == 'deflate':
|
||||
contents = zlib.decompress(contents)
|
||||
inst = cls(u(contents), real_url, headers)
|
||||
except (HTTPError, URLError, socket.timeout, socket.error, OSError, WindowsError):
|
||||
e = sys.exc_info()[1]
|
||||
desc = str(e)
|
||||
if isinstance(e, socket.timeout):
|
||||
log_meth = logger.info
|
||||
level =1
|
||||
desc = 'timed out'
|
||||
elif isinstance(e, URLError):
|
||||
log_meth = logger.info
|
||||
if hasattr(e, 'reason') and isinstance(e.reason, socket.timeout):
|
||||
desc = 'timed out'
|
||||
level = 1
|
||||
else:
|
||||
level = 2
|
||||
elif isinstance(e, HTTPError) and e.code == 404:
|
||||
## FIXME: notify?
|
||||
log_meth = logger.info
|
||||
level = 2
|
||||
else:
|
||||
log_meth = logger.info
|
||||
level = 1
|
||||
log_meth('Could not fetch URL %s: %s' % (link, desc))
|
||||
log_meth('Will skip URL %s when looking for download links for %s' % (link.url, req))
|
||||
if cache is not None:
|
||||
cache.add_page_failure(url, level)
|
||||
return None
|
||||
if cache is not None:
|
||||
cache.add_page([url, real_url], inst)
|
||||
return inst
|
||||
|
||||
@staticmethod
|
||||
def _get_content_type(url):
|
||||
"""Get the Content-Type of the given url, using a HEAD request"""
|
||||
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
|
||||
if not scheme in ('http', 'https', 'ftp', 'ftps'):
|
||||
## FIXME: some warning or something?
|
||||
## assertion error?
|
||||
return ''
|
||||
req = Urllib2HeadRequest(url, headers={'Host': netloc})
|
||||
resp = urlopen(req)
|
||||
try:
|
||||
if hasattr(resp, 'code') and resp.code != 200 and scheme not in ('ftp', 'ftps'):
|
||||
## FIXME: doesn't handle redirects
|
||||
return ''
|
||||
return resp.info().get('content-type', '')
|
||||
finally:
|
||||
resp.close()
|
||||
|
||||
@property
|
||||
def base_url(self):
|
||||
if not hasattr(self, "_base_url"):
|
||||
match = self._base_re.search(self.content)
|
||||
if match:
|
||||
self._base_url = match.group(1)
|
||||
else:
|
||||
self._base_url = self.url
|
||||
return self._base_url
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
"""Yields all links in the page"""
|
||||
for match in self._href_re.finditer(self.content):
|
||||
url = match.group(1) or match.group(2) or match.group(3)
|
||||
url = self.clean_link(urlparse.urljoin(self.base_url, url))
|
||||
yield Link(url, self)
|
||||
|
||||
def rel_links(self):
|
||||
for url in self.explicit_rel_links():
|
||||
yield url
|
||||
for url in self.scraped_rel_links():
|
||||
yield url
|
||||
|
||||
def explicit_rel_links(self, rels=('homepage', 'download')):
|
||||
"""Yields all links with the given relations"""
|
||||
for match in self._rel_re.finditer(self.content):
|
||||
found_rels = match.group(1).lower().split()
|
||||
for rel in rels:
|
||||
if rel in found_rels:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
match = self._href_re.search(match.group(0))
|
||||
if not match:
|
||||
continue
|
||||
url = match.group(1) or match.group(2) or match.group(3)
|
||||
url = self.clean_link(urlparse.urljoin(self.base_url, url))
|
||||
yield Link(url, self)
|
||||
|
||||
def scraped_rel_links(self):
|
||||
for regex in (self._homepage_re, self._download_re):
|
||||
match = regex.search(self.content)
|
||||
if not match:
|
||||
continue
|
||||
href_match = self._href_re.search(self.content, pos=match.end())
|
||||
if not href_match:
|
||||
continue
|
||||
url = href_match.group(1) or href_match.group(2) or href_match.group(3)
|
||||
if not url:
|
||||
continue
|
||||
url = self.clean_link(urlparse.urljoin(self.base_url, url))
|
||||
yield Link(url, self)
|
||||
|
||||
_clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I)
|
||||
|
||||
def clean_link(self, url):
|
||||
"""Makes sure a link is fully encoded. That is, if a ' ' shows up in
|
||||
the link, it will be rewritten to %20 (while not over-quoting
|
||||
% or other characters)."""
|
||||
return self._clean_re.sub(
|
||||
lambda match: '%%%2x' % ord(match.group(0)), url)
|
||||
|
||||
|
||||
class Link(object):
|
||||
|
||||
def __init__(self, url, comes_from=None):
|
||||
self.url = url
|
||||
self.comes_from = comes_from
|
||||
|
||||
def __str__(self):
|
||||
if self.comes_from:
|
||||
return '%s (from %s)' % (self.url, self.comes_from)
|
||||
else:
|
||||
return self.url
|
||||
|
||||
def __repr__(self):
|
||||
return '<Link %s>' % self
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.url == other.url
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.url)
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
url = self.url_fragment
|
||||
name = posixpath.basename(url)
|
||||
assert name, ('URL %r produced no filename' % url)
|
||||
return name
|
||||
|
||||
@property
|
||||
def scheme(self):
|
||||
return urlparse.urlsplit(self.url)[0]
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return urlparse.urlsplit(self.url)[2]
|
||||
|
||||
def splitext(self):
|
||||
return splitext(posixpath.basename(self.path.rstrip('/')))
|
||||
|
||||
@property
|
||||
def url_fragment(self):
|
||||
url = self.url
|
||||
url = url.split('#', 1)[0]
|
||||
url = url.split('?', 1)[0]
|
||||
url = url.rstrip('/')
|
||||
return url
|
||||
|
||||
_egg_fragment_re = re.compile(r'#egg=([^&]*)')
|
||||
|
||||
@property
|
||||
def egg_fragment(self):
|
||||
match = self._egg_fragment_re.search(self.url)
|
||||
if not match:
|
||||
return None
|
||||
return match.group(1)
|
||||
|
||||
_md5_re = re.compile(r'md5=([a-f0-9]+)')
|
||||
|
||||
@property
|
||||
def md5_hash(self):
|
||||
match = self._md5_re.search(self.url)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
@property
|
||||
def show_url(self):
|
||||
return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0])
|
||||
|
||||
|
||||
def get_requirement_from_url(url):
|
||||
"""Get a requirement from the URL, if possible. This looks for #egg
|
||||
in the URL"""
|
||||
link = Link(url)
|
||||
egg_info = link.egg_fragment
|
||||
if not egg_info:
|
||||
egg_info = splitext(link.filename)[0]
|
||||
return package_to_requirement(egg_info)
|
||||
|
||||
|
||||
def package_to_requirement(package_name):
|
||||
"""Translate a name like Foo-1.2 to Foo==1.3"""
|
||||
match = re.search(r'^(.*?)-(dev|\d.*)', package_name)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
version = match.group(2)
|
||||
else:
|
||||
name = package_name
|
||||
version = ''
|
||||
if version:
|
||||
return '%s==%s' % (name, version)
|
||||
else:
|
||||
return name
|
||||
|
||||
|
||||
def get_mirrors(hostname=None):
|
||||
"""Return the list of mirrors from the last record found on the DNS
|
||||
entry::
|
||||
|
||||
>>> from pip.index import get_mirrors
|
||||
>>> get_mirrors()
|
||||
['a.pypi.python.org', 'b.pypi.python.org', 'c.pypi.python.org',
|
||||
'd.pypi.python.org']
|
||||
|
||||
Originally written for the distutils2 project by Alexis Metaireau.
|
||||
"""
|
||||
if hostname is None:
|
||||
hostname = DEFAULT_MIRROR_URL
|
||||
|
||||
# return the last mirror registered on PyPI.
|
||||
try:
|
||||
hostname = socket.gethostbyname_ex(hostname)[0]
|
||||
except socket.gaierror:
|
||||
return []
|
||||
end_letter = hostname.split(".", 1)
|
||||
|
||||
# determine the list from the last one.
|
||||
return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])]
|
||||
|
||||
|
||||
def string_range(last):
|
||||
"""Compute the range of string between "a" and last.
|
||||
|
||||
This works for simple "a to z" lists, but also for "a to zz" lists.
|
||||
"""
|
||||
for k in range(len(last)):
|
||||
for x in product(string.ascii_lowercase, repeat=k+1):
|
||||
result = ''.join(x)
|
||||
yield result
|
||||
if result == last:
|
||||
return
|
||||
|
||||
Vendored
-52
@@ -1,52 +0,0 @@
|
||||
"""Locations where we look for configs, install stuff, etc"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pip.backwardcompat import get_python_lib
|
||||
|
||||
|
||||
def running_under_virtualenv():
|
||||
"""
|
||||
Return True if we're running inside a virtualenv, False otherwise.
|
||||
|
||||
"""
|
||||
return hasattr(sys, 'real_prefix')
|
||||
|
||||
|
||||
if running_under_virtualenv():
|
||||
## FIXME: is build/ a good name?
|
||||
build_prefix = os.path.join(sys.prefix, 'build')
|
||||
src_prefix = os.path.join(sys.prefix, 'src')
|
||||
else:
|
||||
## FIXME: this isn't a very good default
|
||||
build_prefix = os.path.join(os.getcwd(), 'build')
|
||||
src_prefix = os.path.join(os.getcwd(), 'src')
|
||||
|
||||
# under Mac OS X + virtualenv sys.prefix is not properly resolved
|
||||
# it is something like /path/to/python/bin/..
|
||||
build_prefix = os.path.abspath(build_prefix)
|
||||
src_prefix = os.path.abspath(src_prefix)
|
||||
|
||||
# FIXME doesn't account for venv linked to global site-packages
|
||||
|
||||
site_packages = get_python_lib()
|
||||
user_dir = os.path.expanduser('~')
|
||||
if sys.platform == 'win32':
|
||||
bin_py = os.path.join(sys.prefix, 'Scripts')
|
||||
# buildout uses 'bin' on Windows too?
|
||||
if not os.path.exists(bin_py):
|
||||
bin_py = os.path.join(sys.prefix, 'bin')
|
||||
user_dir = os.environ.get('APPDATA', user_dir) # Use %APPDATA% for roaming
|
||||
default_storage_dir = os.path.join(user_dir, 'pip')
|
||||
default_config_file = os.path.join(default_storage_dir, 'pip.ini')
|
||||
default_log_file = os.path.join(default_storage_dir, 'pip.log')
|
||||
else:
|
||||
bin_py = os.path.join(sys.prefix, 'bin')
|
||||
default_storage_dir = os.path.join(user_dir, '.pip')
|
||||
default_config_file = os.path.join(default_storage_dir, 'pip.conf')
|
||||
default_log_file = os.path.join(default_storage_dir, 'pip.log')
|
||||
# Forcing to use /usr/local/bin for standard Mac OS X framework installs
|
||||
# Also log to ~/Library/Logs/ for use with the Console.app log viewer
|
||||
if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/':
|
||||
bin_py = '/usr/local/bin'
|
||||
default_log_file = os.path.join(user_dir, 'Library/Logs/pip.log')
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
[nosetests]
|
||||
where=tests
|
||||
Vendored
-55
@@ -1,55 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
from setuptools import setup
|
||||
|
||||
# If you change this version, change it also in docs/conf.py
|
||||
version = "1.1"
|
||||
|
||||
doc_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "docs")
|
||||
index_filename = os.path.join(doc_dir, "index.txt")
|
||||
news_filename = os.path.join(doc_dir, "news.txt")
|
||||
long_description = """
|
||||
|
||||
The main website for pip is `www.pip-installer.org
|
||||
<http://www.pip-installer.org>`_. You can also install
|
||||
the `in-development version <https://github.com/pypa/pip/tarball/develop#egg=pip-dev>`_
|
||||
of pip with ``easy_install pip==dev``.
|
||||
|
||||
"""
|
||||
f = open(index_filename)
|
||||
# remove the toctree from sphinx index, as it breaks long_description
|
||||
parts = f.read().split("split here", 2)
|
||||
long_description = parts[0] + long_description + parts[2]
|
||||
f.close()
|
||||
f = open(news_filename)
|
||||
long_description += "\n\n" + f.read()
|
||||
f.close()
|
||||
|
||||
setup(name="pip",
|
||||
version=version,
|
||||
description="pip installs packages. Python packages. An easy_install replacement",
|
||||
long_description=long_description,
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.4',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
],
|
||||
keywords='easy_install distutils setuptools egg virtualenv',
|
||||
author='The pip developers',
|
||||
author_email='python-virtualenv@groups.google.com',
|
||||
url='http://www.pip-installer.org',
|
||||
license='MIT',
|
||||
packages=['pip', 'pip.commands', 'pip.vcs'],
|
||||
entry_points=dict(console_scripts=['pip=pip:main', 'pip-%s=pip:main' % sys.version[:3]]),
|
||||
test_suite='nose.collector',
|
||||
tests_require=['nose', 'virtualenv>=1.7', 'scripttest>=1.1.1', 'mock'],
|
||||
zip_safe=False)
|
||||
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
<html><head><title>Links for FSPkg</title></head><body><h1>Links for FSPkg</h1><a href="./FSPkg-0.1dev.tar.gz#md5=ba6e46bed32c5b6d20f974d7d889bdb2">FSPkg-0.1dev.tar.gz</a><br/>
|
||||
<a href="file://../../packages/FSPkg">Source</a><br/>
|
||||
</body></html>
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
This directory has the odd space in its name in order to test urlquoting and
|
||||
dequoting of file:// scheme index URLs.
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
from pip.vcs import subversion, git, bazaar, mercurial
|
||||
from pip.backwardcompat import urlretrieve
|
||||
from tests.test_pip import path_to_url
|
||||
from tests.pypi_server import PyPIProxy
|
||||
|
||||
|
||||
if hasattr(subprocess, "check_call"):
|
||||
subprocess_call = subprocess.check_call
|
||||
else:
|
||||
subprocess_call = subprocess.call
|
||||
|
||||
|
||||
def _create_initools_repository():
|
||||
subprocess_call('svnadmin create INITools'.split(), cwd=_get_vcs_folder())
|
||||
|
||||
|
||||
def _dump_initools_repository():
|
||||
filename, _ = urlretrieve('http://bitbucket.org/hltbra/pip-initools-dump/raw/8b55c908a320/INITools_modified.dump')
|
||||
initools_folder = os.path.join(_get_vcs_folder(), 'INITools')
|
||||
devnull = open(os.devnull, 'w')
|
||||
dump = open(filename)
|
||||
subprocess_call(['svnadmin', 'load', initools_folder], stdin=dump, stdout=devnull)
|
||||
dump.close()
|
||||
devnull.close()
|
||||
os.remove(filename)
|
||||
|
||||
|
||||
def _create_svn_repository_for_initools():
|
||||
tests_cache = _get_vcs_folder()
|
||||
if not os.path.exists(os.path.join(tests_cache, 'INITools')):
|
||||
_create_initools_repository()
|
||||
_dump_initools_repository()
|
||||
|
||||
|
||||
def _get_vcs_folder():
|
||||
folder_name = PyPIProxy.CACHE_PATH
|
||||
if not os.path.exists(folder_name):
|
||||
os.mkdir(folder_name)
|
||||
return folder_name
|
||||
|
||||
|
||||
def _get_vcs_and_checkout_url(remote_repository):
|
||||
tests_cache = _get_vcs_folder()
|
||||
vcs_classes = {'svn': subversion.Subversion,
|
||||
'git': git.Git,
|
||||
'bzr': bazaar.Bazaar,
|
||||
'hg': mercurial.Mercurial}
|
||||
default_vcs = 'svn'
|
||||
if '+' not in remote_repository:
|
||||
remote_repository = '%s+%s' % (default_vcs, remote_repository)
|
||||
vcs, repository_path = remote_repository.split('+', 1)
|
||||
vcs_class = vcs_classes[vcs]
|
||||
branch = ''
|
||||
if vcs == 'svn':
|
||||
branch = os.path.basename(remote_repository)
|
||||
repository_name = os.path.basename(remote_repository[:-len(branch)-1]) # remove the slash
|
||||
else:
|
||||
repository_name = os.path.basename(remote_repository)
|
||||
|
||||
destination_path = os.path.join(tests_cache, repository_name)
|
||||
if not os.path.exists(destination_path):
|
||||
vcs_class(remote_repository).obtain(destination_path)
|
||||
return '%s+%s' % (vcs, path_to_url('/'.join([tests_cache, repository_name, branch])))
|
||||
|
||||
|
||||
def local_checkout(remote_repo):
|
||||
if remote_repo.startswith('svn'):
|
||||
_create_svn_repository_for_initools()
|
||||
return _get_vcs_and_checkout_url(remote_repo)
|
||||
|
||||
|
||||
def local_repo(remote_repo):
|
||||
return local_checkout(remote_repo).split('+', 1)[1]
|
||||
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from distutils.core import setup
|
||||
import sys
|
||||
|
||||
class FakeError(Exception):
|
||||
pass
|
||||
|
||||
if sys.argv[1] == 'install':
|
||||
if hasattr(sys.stdout, 'buffer'):
|
||||
sys.stdout.buffer.write('\nThis package prints out UTF-8 stuff like:\n'.encode('utf-8'))
|
||||
sys.stdout.buffer.write('* return type of ‘main’ is not ‘int’\n'.encode('utf-8'))
|
||||
sys.stdout.buffer.write('* Björk Guðmundsdóttir [ˈpjœr̥k ˈkvʏðmʏntsˌtoʊhtɪr]'.encode('utf-8'))
|
||||
else:
|
||||
pass
|
||||
sys.stdout.write('\nThis package prints out UTF-8 stuff like:\n')
|
||||
sys.stdout.write('* return type of \xe2\x80\x98main\xe2\x80\x99 is not \xe2\x80\x98int\xe2\x80\x99\n')
|
||||
sys.stdout.write('* Bj\xc3\xb6rk Gu\xc3\xb0mundsd\xc3\xb3ttir [\xcb\x88pj\xc5\x93r\xcc\xa5k \xcb\x88kv\xca\x8f\xc3\xb0m\xca\x8fnts\xcb\x8cto\xca\x8aht\xc9\xaar]\n')
|
||||
|
||||
raise FakeError('this package designed to fail on install')
|
||||
|
||||
setup(name='broken',
|
||||
version='0.2broken',
|
||||
py_modules=['broken'],
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
#
|
||||
@@ -1,3 +0,0 @@
|
||||
[egg_info]
|
||||
tag_build = dev
|
||||
tag_svn_revision = true
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
version = '0.1'
|
||||
|
||||
setup(name='FSPkg',
|
||||
version=version,
|
||||
description="File system test package",
|
||||
long_description="""\
|
||||
File system test package""",
|
||||
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
keywords='pip tests',
|
||||
author='pip',
|
||||
author_email='pip@openplans.org',
|
||||
url='http://pip.openplans.org',
|
||||
license='',
|
||||
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
install_requires=[
|
||||
# -*- Extra requirements: -*-
|
||||
],
|
||||
entry_points="""
|
||||
# -*- Entry points: -*-
|
||||
""",
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
from distutils.core import setup
|
||||
|
||||
setup()
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
This package exists for testing uninstall-rollback.
|
||||
|
||||
Version 0.2broken has a setup.py crafted to fail on install (and only on
|
||||
install). If any earlier step would fail (i.e. egg-info-generation), the
|
||||
already-installed version would never be uninstalled, so uninstall-rollback
|
||||
would not come into play.
|
||||
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Vendored
-209
@@ -1,209 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Author: Aziz Köksal
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
unicode = str
|
||||
u = str
|
||||
else:
|
||||
unicode = unicode
|
||||
u = lambda s: s.decode('utf-8')
|
||||
|
||||
_base = os.path.supports_unicode_filenames and unicode or str
|
||||
|
||||
from pip.util import rmtree
|
||||
|
||||
|
||||
class Path(_base):
|
||||
""" Models a path in an object oriented way. """
|
||||
|
||||
sep = os.sep # File system path separator: '/' or '\'.
|
||||
pathsep = os.pathsep # Separator in the PATH environment variable.
|
||||
string = _base
|
||||
|
||||
def __new__(cls, *paths):
|
||||
if len(paths):
|
||||
return _base.__new__(cls, os.path.join(*paths))
|
||||
return _base.__new__(cls)
|
||||
|
||||
def __div__(self, path):
|
||||
""" Joins this path with another path. """
|
||||
""" path_obj / 'bc.d' """
|
||||
""" path_obj / path_obj2 """
|
||||
return Path(self, path)
|
||||
|
||||
__truediv__ = __div__
|
||||
|
||||
def __rdiv__(self, path):
|
||||
""" Joins this path with another path. """
|
||||
""" "/home/a" / path_obj """
|
||||
return Path(path, self)
|
||||
|
||||
__rtruediv__ = __rdiv__
|
||||
|
||||
def __idiv__(self, path):
|
||||
""" Like __div__ but also assigns to the variable. """
|
||||
""" path_obj /= 'bc.d' """
|
||||
return Path(self, path)
|
||||
|
||||
__itruediv__ = __idiv__
|
||||
|
||||
def __floordiv__(self, paths):
|
||||
""" Returns a list of paths prefixed with 'self'. """
|
||||
""" '/home/a' // [bc.d, ef.g] -> [/home/a/bc.d, /home/a/ef.g] """
|
||||
return [Path(self, path) for path in paths]
|
||||
|
||||
def __sub__(self, path):
|
||||
""" Makes this path relative to another path. """
|
||||
""" path_obj - '/home/a' """
|
||||
""" path_obj - path_obj2 """
|
||||
return Path(os.path.relpath(self, path))
|
||||
|
||||
def __rsub__(self, path):
|
||||
""" Returns path relative to this path. """
|
||||
""" "/home/a" - path_obj """
|
||||
return Path(os.path.relpath(path, self))
|
||||
|
||||
def __add__(self, path):
|
||||
""" Path('/home/a') + 'bc.d' -> '/home/abc.d' """
|
||||
return Path(_base(self) + path)
|
||||
|
||||
def __radd__(self, path):
|
||||
""" '/home/a' + Path('bc.d') -> '/home/abc.d' """
|
||||
return Path(path + _base(self))
|
||||
|
||||
def __repr__(self):
|
||||
return u("Path(%s)" % _base.__repr__(self))
|
||||
|
||||
def __hash__(self):
|
||||
return _base.__hash__(self)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" '/home/a/bc.d' -> 'bc.d' """
|
||||
return os.path.basename(self)
|
||||
|
||||
@property
|
||||
def namebase(self):
|
||||
""" '/home/a/bc.d' -> 'bc' """
|
||||
return self.noext.name
|
||||
|
||||
@property
|
||||
def noext(self):
|
||||
""" '/home/a/bc.d' -> '/home/a/bc' """
|
||||
return Path(os.path.splitext(self)[0])
|
||||
|
||||
@property
|
||||
def ext(self):
|
||||
""" '/home/a/bc.d' -> '.d' """
|
||||
return Path(os.path.splitext(self)[1])
|
||||
|
||||
@property
|
||||
def abspath(self):
|
||||
""" './a/bc.d' -> '/home/a/bc.d' """
|
||||
return Path(os.path.abspath(self))
|
||||
|
||||
@property
|
||||
def realpath(self):
|
||||
""" Resolves symbolic links. """
|
||||
return Path(os.path.realpath(self))
|
||||
|
||||
@property
|
||||
def normpath(self):
|
||||
""" '/home/x/.././a//bc.d' -> '/home/a/bc.d' """
|
||||
return Path(os.path.normpath(self))
|
||||
|
||||
@property
|
||||
def normcase(self):
|
||||
""" Deals with case-insensitive filesystems """
|
||||
return Path(os.path.normcase(self))
|
||||
|
||||
@property
|
||||
def folder(self):
|
||||
""" Returns the folder of this path. """
|
||||
""" '/home/a/bc.d' -> '/home/a' """
|
||||
""" '/home/a/' -> '/home/a' """
|
||||
""" '/home/a' -> '/home' """
|
||||
return Path(os.path.dirname(self))
|
||||
|
||||
@property
|
||||
def exists(self):
|
||||
""" Returns True if the path exists. """
|
||||
return os.path.exists(self)
|
||||
|
||||
@property
|
||||
def atime(self):
|
||||
""" Returns last accessed time. """
|
||||
return os.path.getatime(self)
|
||||
|
||||
@property
|
||||
def mtime(self):
|
||||
""" Returns last modified time. """
|
||||
return os.path.getmtime(self)
|
||||
|
||||
@property
|
||||
def ctime(self):
|
||||
""" Returns last changed time. """
|
||||
return os.path.getctime(self)
|
||||
|
||||
@classmethod
|
||||
def supports_unicode(self):
|
||||
""" Returns True if the system can handle Unicode file names. """
|
||||
return os.path.supports_unicode_filenames()
|
||||
|
||||
def walk(self, **kwargs):
|
||||
""" Returns a generator that walks through a directory tree. """
|
||||
if "followlinks" in kwargs:
|
||||
from sys import version_info as vi
|
||||
if vi[0]*10+vi[1] < 26: # Only Python 2.6 or newer supports followlinks
|
||||
del kwargs["followlinks"]
|
||||
return os.walk(self, **kwargs)
|
||||
|
||||
def mkdir(self, mode=0x1FF): # 0o777
|
||||
""" Creates a directory, if it doesn't exist already. """
|
||||
if not self.exists:
|
||||
os.mkdir(self, mode)
|
||||
|
||||
def makedirs(self, mode=0x1FF): # 0o777
|
||||
""" Like mkdir(), but also creates parent directories. """
|
||||
if not self.exists:
|
||||
os.makedirs(self, mode)
|
||||
|
||||
def remove(self):
|
||||
""" Removes a file. """
|
||||
os.remove(self)
|
||||
rm = remove # Alias.
|
||||
|
||||
def rmdir(self):
|
||||
""" Removes a directory. """
|
||||
return os.rmdir(self)
|
||||
|
||||
def rmtree(self, noerrors=True):
|
||||
""" Removes a directory tree. Ignores errors by default. """
|
||||
return rmtree(self, ignore_errors=noerrors)
|
||||
|
||||
def copy(self, to):
|
||||
shutil.copy(self, to)
|
||||
|
||||
def copytree(self, to):
|
||||
""" Copies a directory tree to another path. """
|
||||
shutil.copytree(self, to)
|
||||
|
||||
def move(self, to):
|
||||
""" Moves a file or directory to another path. """
|
||||
shutil.move(self, to)
|
||||
|
||||
def rename(self, to):
|
||||
""" Renames a file or directory. May throw an OSError. """
|
||||
os.rename(self, to)
|
||||
|
||||
def renames(self, to):
|
||||
os.renames(self, to)
|
||||
|
||||
def glob(self, pattern):
|
||||
from glob import glob
|
||||
return list(map(Path, glob(_base(self/pattern))))
|
||||
|
||||
curdir = Path(os.path.curdir)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user