mirror of
https://github.com/kennethreitz/heroku-buildpack-python.git
synced 2026-06-05 23:10:16 +00:00
Compare commits
78 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 | |||
| 0ff4df4dc3 | |||
| 9177aa2c08 | |||
| ad791dc7f8 | |||
| 6b298ff7f3 | |||
| 01e30e938c |
@@ -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
|
-----> Fetching custom git buildpack... done
|
||||||
-----> Python app detected
|
-----> Python app detected
|
||||||
-----> No runtime.txt provided; assuming python-2.7.3.
|
-----> No runtime.txt provided; assuming python-2.7.6.
|
||||||
-----> Preparing Python runtime (python-2.7.3)
|
-----> Preparing Python runtime (python-2.7.6)
|
||||||
-----> Installing Distribute (0.6.34)
|
-----> Installing Setuptools (2.1)
|
||||||
-----> Installing Pip (1.2.1)
|
-----> Installing Pip (1.5.2)
|
||||||
-----> Installing dependencies using Pip (1.2.1)
|
-----> Installing dependencies using Pip (1.5.2)
|
||||||
Downloading/unpacking Flask==0.7.2 (from -r requirements.txt (line 1))
|
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 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))
|
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
|
$ 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
|
Specify a Runtime
|
||||||
-----------------
|
-----------------
|
||||||
@@ -45,10 +45,12 @@ Specify a Runtime
|
|||||||
You can also provide arbitrary releases Python with a `runtime.txt` file.
|
You can also provide arbitrary releases Python with a `runtime.txt` file.
|
||||||
|
|
||||||
$ cat runtime.txt
|
$ cat runtime.txt
|
||||||
python-3.3.0
|
python-3.3.3
|
||||||
|
|
||||||
Runtime options include:
|
Runtime options include:
|
||||||
|
|
||||||
- python-2.7.3
|
- python-2.7.6
|
||||||
- python-3.3.0
|
- python-3.3.3
|
||||||
- pypy-1.9 (experimental)
|
- pypy-1.9 (experimental)
|
||||||
|
|
||||||
|
Other [unsupported runtimes](https://github.com/kennethreitz/python-versions/tree/master/formula) are available as well.
|
||||||
|
|||||||
+143
-85
@@ -1,33 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# This script serves as the
|
# Usage:
|
||||||
# [**Python Buildpack**](https://github.com/heroku/heroku-buildpack-python)
|
|
||||||
# compiler.
|
|
||||||
#
|
#
|
||||||
# A [buildpack](http://devcenter.heroku.com/articles/buildpacks) is an
|
# $ bin/compile <build-dir> <cache-dir> <env-path>
|
||||||
# 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
|
|
||||||
|
|
||||||
# Fail fast and fail hard.
|
# Fail fast and fail hard.
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
@@ -40,6 +15,8 @@ BIN_DIR=$(cd $(dirname $0); pwd) # absolute path
|
|||||||
ROOT_DIR=$(dirname $BIN_DIR)
|
ROOT_DIR=$(dirname $BIN_DIR)
|
||||||
BUILD_DIR=$1
|
BUILD_DIR=$1
|
||||||
CACHE_DIR=$2
|
CACHE_DIR=$2
|
||||||
|
ENV_DIR=$3
|
||||||
|
|
||||||
|
|
||||||
CACHED_DIRS=".heroku"
|
CACHED_DIRS=".heroku"
|
||||||
|
|
||||||
@@ -48,13 +25,30 @@ VIRTUALENV_LOC=".heroku/venv"
|
|||||||
LEGACY_TRIGGER="lib/python2.7"
|
LEGACY_TRIGGER="lib/python2.7"
|
||||||
PROFILE_PATH="$BUILD_DIR/.profile.d/python.sh"
|
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.6"
|
||||||
DEFAULT_PYTHON_VERSION="python-2.7.3"
|
|
||||||
PYTHON_EXE="/app/.heroku/python/bin/python"
|
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.
|
# Sanitizing environment variables.
|
||||||
unset GIT_DIR PYTHONHOME PYTHONPATH LD_LIBRARY_PATH LIBRARY_PATH
|
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`.
|
# We'll need to send these statics to other scripts we `source`.
|
||||||
export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH
|
export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH
|
||||||
|
|
||||||
@@ -66,28 +60,41 @@ APP_DIR='/app'
|
|||||||
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
|
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
|
||||||
|
|
||||||
# Copy Anvil app dir to temporary storage...
|
# Copy Anvil app dir to temporary storage...
|
||||||
mkdir -p $TMP_APP_DIR
|
bpwatch start anvil_appdir_stage
|
||||||
deep-mv $APP_DIR $TMP_APP_DIR
|
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.
|
# 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.
|
# Set new context.
|
||||||
ORIG_BUILD_DIR=$BUILD_DIR
|
ORIG_BUILD_DIR=$BUILD_DIR
|
||||||
BUILD_DIR=$APP_DIR
|
BUILD_DIR=$APP_DIR
|
||||||
|
|
||||||
# Prepend proper path buildpack use.
|
# 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
|
export PYTHONUNBUFFERED=1
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
# ## Build Time
|
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.
|
# Switch to the repo's context.
|
||||||
cd $BUILD_DIR
|
cd $BUILD_DIR
|
||||||
|
|
||||||
# Experimental pre_compile hook.
|
# 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 no requirements given, assume `setup.py develop`.
|
||||||
if [ ! -f requirements.txt ]; then
|
if [ ! -f requirements.txt ]; then
|
||||||
@@ -95,6 +102,11 @@ if [ ! -f requirements.txt ]; then
|
|||||||
echo "-e ." > requirements.txt
|
echo "-e ." > requirements.txt
|
||||||
fi
|
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 no runtime given, assume default version.
|
||||||
if [ ! -f runtime.txt ]; then
|
if [ ! -f runtime.txt ]; then
|
||||||
puts-step "No runtime.txt provided; assuming $DEFAULT_PYTHON_VERSION."
|
puts-step "No runtime.txt provided; assuming $DEFAULT_PYTHON_VERSION."
|
||||||
@@ -105,13 +117,17 @@ fi
|
|||||||
mkdir -p $CACHE_DIR
|
mkdir -p $CACHE_DIR
|
||||||
|
|
||||||
# Purge "old-style" virtualenvs.
|
# Purge "old-style" virtualenvs.
|
||||||
[ -d $CACHE_DIR/$LEGACY_TRIGGER ] && rm -fr $CACHE_DIR/.heroku/bin $CACHE_DIR/.heroku/lib $CACHE_DIR/.heroku/include
|
bpwatch start clear_old_venvs
|
||||||
[ -d $CACHE_DIR/$VIRTUALENV_LOC ] && rm -fr $CACHE_DIR/.heroku/venv $CACHE_DIR/.heroku/src
|
[ -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.
|
# Restore old artifacts from the cache.
|
||||||
for dir in $CACHED_DIRS; do
|
bpwatch start restore_cache
|
||||||
cp -R $CACHE_DIR/$dir . &> /dev/null || true
|
for dir in $CACHED_DIRS; do
|
||||||
done
|
cp -R $CACHE_DIR/$dir . &> /dev/null || true
|
||||||
|
done
|
||||||
|
bpwatch stop restore_cache
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
# Create set-aside `.heroku` folder.
|
# Create set-aside `.heroku` folder.
|
||||||
@@ -126,8 +142,10 @@ PYTHON_VERSION=$(cat runtime.txt)
|
|||||||
# Install Python.
|
# Install Python.
|
||||||
if [ -f .heroku/python-version ]; then
|
if [ -f .heroku/python-version ]; then
|
||||||
if [ ! $(cat .heroku/python-version) = $PYTHON_VERSION ]; then
|
if [ ! $(cat .heroku/python-version) = $PYTHON_VERSION ]; then
|
||||||
puts-step "Found $(cat .heroku/python-version), removing."
|
bpwatch start uninstall_python
|
||||||
rm -fr .heroku/python
|
puts-step "Found $(cat .heroku/python-version), removing."
|
||||||
|
rm -fr .heroku/python
|
||||||
|
bpwatch stop uninstall_python
|
||||||
else
|
else
|
||||||
SKIP_INSTALL=1
|
SKIP_INSTALL=1
|
||||||
fi
|
fi
|
||||||
@@ -135,79 +153,119 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
if [ ! "$SKIP_INSTALL" ]; then
|
if [ ! "$SKIP_INSTALL" ]; then
|
||||||
puts-step "Preparing Python runtime ($PYTHON_VERSION)"
|
bpwatch start install_python
|
||||||
curl http://envy-versions.s3.amazonaws.com/$PYTHON_VERSION.tar.bz2 -s | tar jx &> /dev/null
|
puts-step "Preparing Python runtime ($PYTHON_VERSION)"
|
||||||
if [[ $? != 0 ]] ; then
|
curl http://envy-versions.s3.amazonaws.com/$PYTHON_VERSION.tar.bz2 -s | tar jx &> /dev/null
|
||||||
puts-warn "Requested runtime ($PYTHON_VERSION) was not found."
|
if [[ $? != 0 ]] ; then
|
||||||
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
puts-warn "Requested runtime ($PYTHON_VERSION) was not found."
|
||||||
exit 1
|
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
||||||
fi
|
exit 1
|
||||||
mv python .heroku/python
|
fi
|
||||||
|
mv python .heroku/python
|
||||||
|
bpwatch stop install_python
|
||||||
|
|
||||||
# Record for future reference.
|
# Record for future reference.
|
||||||
echo $PYTHON_VERSION > .heroku/python-version
|
echo $PYTHON_VERSION > .heroku/python-version
|
||||||
WORKING_DIR=$(pwd)
|
FRESH_PYTHON=true
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
hash -r
|
hash -r
|
||||||
else
|
else
|
||||||
puts-step "Using Python runtime ($PYTHON_VERSION)"
|
puts-step "Using Python runtime ($PYTHON_VERSION)"
|
||||||
fi
|
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
|
set -e
|
||||||
|
hash -r
|
||||||
|
|
||||||
# Pylibmc support.
|
# Pylibmc support.
|
||||||
# See [`bin/steps/pylibmc`](pylibmc.html).
|
# 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.
|
# Install Mercurial if it appears to be required.
|
||||||
if (in-req "hg+" requirements.txt) then
|
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
|
fi
|
||||||
|
|
||||||
# Install dependencies with Pip.
|
# Install dependencies with Pip.
|
||||||
puts-step "Installing dependencies using Pip (1.2.1)"
|
puts-step "Installing dependencies using Pip ($PIP_VERSION)"
|
||||||
pip install --use-mirrors -r requirements.txt --exists-action=w --src=./.heroku/src | cleanup | indent
|
|
||||||
|
|
||||||
|
[ ! "$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.
|
# Django collectstatic support.
|
||||||
source $BIN_DIR/steps/collectstatic
|
bpwatch start collectstatic
|
||||||
|
sub-env $BIN_DIR/steps/collectstatic
|
||||||
|
bpwatch stop collectstatic
|
||||||
|
|
||||||
# ### Finalize
|
# ### 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 context environment variables.
|
||||||
set-env PATH '$HOME/.heroku/python/bin:$PATH'
|
set-env PATH '$HOME/.heroku/python/bin:$PATH'
|
||||||
# set-env PYTHONHOME /app/.heroku/python/
|
|
||||||
set-env PYTHONUNBUFFERED true
|
set-env PYTHONUNBUFFERED true
|
||||||
|
set-env PYTHONHOME /app/.heroku/python
|
||||||
set-default-env LIBRARY_PATH /app/.heroku/vendor/lib
|
set-default-env LIBRARY_PATH /app/.heroku/vendor/lib
|
||||||
set-default-env LD_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 LANG en_US.UTF-8
|
||||||
set-default-env PYTHONHASHSEED random
|
set-default-env PYTHONHASHSEED random
|
||||||
set-default-env PYTHONPATH /app/
|
set-default-env PYTHONPATH /app/
|
||||||
un-set-env PYTHONHOME
|
|
||||||
|
|
||||||
|
|
||||||
# ### Fin.
|
|
||||||
|
|
||||||
deep-mv $BUILD_DIR $ORIG_BUILD_DIR
|
|
||||||
deep-mv $TMP_APP_DIR $APP_DIR
|
|
||||||
|
|
||||||
|
|
||||||
# Experimental post_compile hook.
|
# 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
|
||||||
|
|
||||||
|
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
|
cat <<EOF
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
shared-database:5mb
|
heroku-postgresql:hobby-dev
|
||||||
EOF
|
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=$(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
|
[ -f .heroku/collectstatic_disabled ] && DISABLE_COLLECTSTATIC=1
|
||||||
DISABLE_COLLECTSTATIC=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! "$DISABLE_COLLECTSTATIC" ]; then
|
if [ ! "$DISABLE_COLLECTSTATIC" ] && [ -f "$MANAGE_FILE" ]; then
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
# Check if collectstatic is configured properly.
|
# Check if collectstatic is configured properly.
|
||||||
|
|||||||
Regular → Executable
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
if [ -f bin/post_compile ]; then
|
if [ -f bin/post_compile ]; then
|
||||||
echo "-----> Running post-compile hook"
|
echo "-----> Running post-compile hook"
|
||||||
chmod +x bin/post_compile
|
chmod +x bin/post_compile
|
||||||
bin/post_compile
|
sub-env bin/post_compile
|
||||||
fi
|
fi
|
||||||
Regular → Executable
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
if [ -f bin/pre_compile ]; then
|
if [ -f bin/pre_compile ]; then
|
||||||
echo "-----> Running pre-compile hook"
|
echo "-----> Running pre-compile hook"
|
||||||
chmod +x bin/pre_compile
|
chmod +x bin/pre_compile
|
||||||
bin/pre_compile
|
sub-env bin/pre_compile
|
||||||
fi
|
fi
|
||||||
+1
-1
@@ -16,7 +16,7 @@ VENDORED_MEMCACHED="http://cl.ly/0a191R3K160t1w1P0N25/vendor-libmemcached.tar.gz
|
|||||||
source $BIN_DIR/utils
|
source $BIN_DIR/utils
|
||||||
|
|
||||||
# If pylibmc exists within requirements, use vendored libmemcached.
|
# If pylibmc exists within requirements, use vendored libmemcached.
|
||||||
if (in-req "pylibmc" requirements.txt) then
|
if (grep -Eiq "^\s*pylibmc" requirements.txt) then
|
||||||
echo "-----> Noticed pylibmc. Bootstrapping libmemcached."
|
echo "-----> Noticed pylibmc. Bootstrapping libmemcached."
|
||||||
cd .heroku
|
cd .heroku
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Create a Heroku app with the following buildpack:
|
# 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
|
# Push this Python buildpack to that Heroku app to
|
||||||
# run the tests.
|
# run the tests.
|
||||||
@@ -20,6 +20,12 @@ testDetectWithEmptyReqs() {
|
|||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testDetectDjango15() {
|
||||||
|
detect "django-1.5-skeleton"
|
||||||
|
assertCapturedEquals "Python"
|
||||||
|
assertCapturedSuccess
|
||||||
|
}
|
||||||
|
|
||||||
testDetectDjango14() {
|
testDetectDjango14() {
|
||||||
detect "django-1.4-skeleton"
|
detect "django-1.4-skeleton"
|
||||||
assertCapturedEquals "Python"
|
assertCapturedEquals "Python"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
Script started on Wed Dec 19 22:40:46 2012
|
|
||||||
[1m[7m%[27m[1m[0m
|
|
||||||
|
|
||||||
@@ -53,24 +53,28 @@ function deep-mv (){
|
|||||||
find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
|
find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Recursively finds requirements.txt files
|
# Does some serious deleting.
|
||||||
function list-req (){
|
function deep-rm (){
|
||||||
echo $@
|
rm -fr $1/!(tmp)
|
||||||
for req in $(grep -Fie "-r " $@ | sed 's/-r //g')
|
find -H $1 -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec rm -fr '{}' \;
|
||||||
do
|
|
||||||
path="$(dirname $@)/$req"
|
|
||||||
list-req $path
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find pattern in requirements files recursively
|
|
||||||
# Usage: $ in-req pattern file
|
sub-env() {
|
||||||
function in-req (){
|
|
||||||
for file in $(list-req $2)
|
WHITELIST=${2:-''}
|
||||||
do
|
BLACKLIST=${3:-'^(GIT_DIR|PYTHONHOME|PYTHONPATH|LD_LIBRARY_PATH|LIBRARY_PATH|PATH)$'}
|
||||||
if (grep -Fiqe "$1" "$file") then
|
|
||||||
return 0
|
(
|
||||||
fi
|
if [ -d "$ENV_DIR" ]; then
|
||||||
done
|
for e in $(ls $ENV_DIR); do
|
||||||
return 1
|
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