Commit 5ae51010 authored by Kenneth Reitz's avatar Kenneth Reitz

update pip to v0.3.1

parent 29d8e7f6
Alex Grönholm
Alex Morega
Alexandre Conrad
Andrey Bulgakov
Antti Kaihola
Armin Ronacher
Aziz Köksal
Ben Rosser
Brian Rosner
Carl Meyer
Chris McDonough
Christian Oudard
Clay McClure
Cody Soyland
Daniel Holth
Dave Abrahams
David (d1b)
Dmitry Gladkov
Donald Stufft
Francesco
Geoffrey Lehée
Georgi Valkov
Hugo Lopes Tavares
Ian Bicking
Igor Sobreira
Ionel Maries Cristian
Jakub Vysoky
James Cleveland
Jannis Leidel
Jay Graves
John-Scott Atlakson
Jon Parise
Jonas Nockert
Josh Bronson
Kamal Bin Mustafa
Kelsey Hightower
Kenneth Belitzky
Kumar McMillan
Luke Macken
Masklinn
Marc Abramowitz
Marcus Smith
Markus Hametner
Matt Maker
Maxime R.
Miguel Araujo
Nick Stenning
Nowell Strite
Oliver Tonnhofer
Olivier Girardot
Patrick Jenkins
Paul Moore
Paul Nasrat
Paul Oswald
Paul van der Linden
Peter Waller
Phil Whelan
Piet Delport
Przemek Wrzos
Qiangning Hong
Rafael Caricio
Rene Dudfield
Roey Berman
Ronny Pfannschmidt
Rory McCann
Simon Cross
Stavros Korokithakis
Thomas Fenzl
Thomas Johansson
Vinay Sajip
Vitaly Babiy
W Trevor King
Wil Tan
Hsiaoming Yang
This diff is collapsed.
Copyright (c) 2008-2013 The pip developers (see AUTHORS.txt file)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License for Bundle of CA Root Certificates (pip/cacert.pem)
===========================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301
include AUTHORS.txt
include LICENSE.txt
include CHANGES.txt
include PROJECT.txt
include pip/cacert.pem
recursive-include docs *.txt
recursive-include docs *.html
recursive-exclude docs/_build *.txt
prune docs/_build/_sources
This diff is collapsed.
Project Info
============
* Project Page: https://github.com/pypa/pip
* Bug Tracking: https://github.com/pypa/pip/issues
* Mailing list: http://groups.google.com/group/python-virtualenv
* Docs: http://www.pip-installer.org
* IRC: #pip.
pip
===
.. image:: https://secure.travis-ci.org/pypa/pip.png?branch=develop
:target: http://travis-ci.org/pypa/pip
For documentation, see http://www.pip-installer.org
.. _`Configuration`:
Configuration
=================
Config file
------------
pip allows you to set all command line option defaults in a standard ini
style config file.
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`
* On Windows, the configuration file is: :file:`%HOME%\\pip\\pip.ini`
You can set a custom path location for the config file using the environment variable ``PIP_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
Environment Variables
---------------------
pip's command line options can be set with
environment variables using the format ``PIP_<UPPER_LONG_NAME>`` . Dashes (``-``) have to replaced with underscores (``_``).
For example, to set the default timeout::
export PIP_DEFAULT_TIMEOUT=60
This is the same as passing the option to pip directly::
pip --default-timeout=60 [...]
To set options that can be set multiple times on the command line, just add spaces in between values. For example::
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
Config Precedence
-----------------
Command line options have precedence over environment variables, which have precedence over the config file.
Within the config file, command specific sections have precedence over the global section.
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
Command Completion
------------------
pip comes with support for command line completion in bash and zsh.
To setup for bash::
$ pip completion --bash >> ~/.profile
To setup 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 the following to your startup file::
eval "`pip completion --bash`"
============
Cookbook
============
.. _`Requirements Files`:
Requirements Files
******************
A key idea in pip is that package versions listed in requirement files (or as :ref:`pip install` arguments),
have precedence over those that are located during the normal dependency resolution process that uses "install_requires" metadata.
This allows users to be in control of specifying an environment of packages that are known to work together.
Instead of running something like ``pip install MyApp`` and getting whatever libraries come along,
you'd run ``pip install -r requirements.txt`` where "requirements.txt" contains something like::
MyApp
Framework==0.9.4
Library>=0.2
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. Additionally, you can add optional libraries and support tools that MyApp doesn't strictly
require, giving people a set of recommended libraries.
Requirement files are intended to exhaust an environment and to be *flat*.
Maybe ``MyApp`` requires ``Framework``, and ``Framework`` requires ``Library``.
It is encouraged 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.
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.
For more information, see:
* :ref:`Requirements File Format`
* :ref:`pip freeze`
.. _`Downloading Archives`:
Downloading archives
********************
pip allows you to *just* download the source archives for your requirements, without installing anything and without regard to what's already installed.
::
$ pip install --download <DIR> -r requirements.txt
or, for a specific package::
$ pip install --download <DIR> SomePackage
Unpacking archives
******************
pip allows you to *just* unpack archives to a build directory without installing them to site-packages. This can be useful to troubleshoot install errors or to inspect what is being installed.
::
$ pip install --no-install SomePackage
If you're in a virtualenv, the build dir is ``<virtualenv path>/build``. Otherwise, it's ``<OS temp dir>/pip-build-<username>``
Afterwards, to finish the job of installing unpacked archives, run::
$ pip install --no-download SomePackage
.. _`Fast & Local Installs`:
Fast & Local Installs
*********************
Often, you will want a fast install from local archives, without probing PyPI.
First, :ref:`download the archives <Downloading Archives>` that fulfill your requirements::
$ pip install --download <DIR> -r requirements.txt
Then, install using :ref:`--find-links <--find-links>` and :ref:`--no-index <--no-index>`::
$ pip install --no-index --find-links=[file://]<DIR> -r requirements.txt
"Non-recursive" upgrades
************************
``pip install ---upgrade`` is currently written to perform a "recursive upgrade".
E.g. supposing:
* `SomePackage-1.0` requires `AnotherPackage>=1.0`
* `SomePackage-2.0` requires `AnotherPackage>=1.0` and `OneMorePoject==1.0`
* `SomePackage-1.0` and `AnotherPackage-1.0` are currently installed
* `SomePackage-2.0` and `AnotherPackage-2.0` are the latest versions available on PyPI.
Running ``pip install ---upgrade SomePackage`` would upgrade `SomePackage` *and* `AnotherPackage`
despite `AnotherPackage` already being satisifed.
If you would like to perform a "non-recursive upgrade" perform these 2 steps::
pip install --upgrade --no-deps SomePackage
pip install SomePackage
The first line will upgrade `SomePackage`, but not dependencies like `AnotherPackage`. The 2nd line will fill in new dependencies like `OneMorePackage`.
Ensuring Repeatability
**********************
Three things are required to fully guarantee a repeatable installation using requirements files.
1. The requirements file was generated by ``pip freeze`` or you're sure it only contains requirements that specify a specific version.
2. The installation is performed using :ref:`--no-deps <install_--no-deps>`. This guarantees that only what is explicitly listed in the requirements file is installed.
3. The installation is performed against an index or find-links location that is guaranteed to *not* allow archives to be changed and updated without a version increase.
===========
Development
===========
Pull Requests
=============
Submit Pull Requests against the `develop` branch.
Provide a good description of what you're doing and why.
Provide tests that cover your changes and try to run the tests locally first.
Automated Testing
=================
All pull requests and merges to 'develop' branch are tested in `Travis <https://travis-ci.org/>`_
based on our `.travis.yml file <https://github.com/pypa/pip/blob/develop/.travis.yml>`_.
Usually, a link to your specific travis build appears in pull requests, but if not,
you can find it on our `travis pull requests page <https://travis-ci.org/pypa/pip/pull_requests>`_
The only way to trigger Travis to run again for a pull request, is to submit another change to the pull branch.
We also have Jenkins CI that runs regularly for certain python versions on windows and centos.
Running tests
=============
OS Requirements: subversion, bazaar, git, and mercurial.
Python Requirements: nose, virtualenv, scripttest, and mock
Ways to run the tests locally:
::
$ python setup.py test # Using the setuptools test plugin
$ nosetests # Using nosetests directly
$ tox # Using tox against pip's tox.ini
Getting Involved
================
The pip project welcomes help in the following ways:
- Making Pull Requests for code, tests, or docs.
- Commenting on open issues and pull requests.
- Helping to answer questions on the mailing list.
If you want to become an official maintainer, start by helping out.
Later, when you think you're ready, get in touch with one of the maintainers,
and they will initiate a vote.
Release Process
===============
This process includes virtualenv, since pip releases necessitate a virtualenv release.
:<oldp>/<newp>: refers to the old and new versions of pip.
:<oldv>/<newv>: refers to the old and new versions of virtualenv.
1. Upgrade distribute, if needed:
#. Upgrade distribute in ``virtualenv:develop`` using the :ref:`Refresh virtualenv` process.
#. Create a pull request against ``pip:develop`` with a modified ``.travis.yml`` file that installs virtualenv from ``virtualenv:develop``, to confirm the travis builds are still passing.
2. Create Release branches:
#. Create ``pip:<newp>`` branch.
#. In ``pip:develop``, change ``pip.version`` to '<newp>.post1'.
#. Create ``virtualenv:<newv>`` branch.
#. In ``virtualenv:develop``, change ``virtualenv.version`` to '<newv>.post1'.
3. Prepare "rcX":
#. In ``pip:<newp>``, change ``pip.version`` to '<newp>rcX', and tag with '<newp>rcX'.
#. Build a pip sdist from ``pip:<newp>``, and build it into ``virtualenv:<newv>`` using the :ref:`Refresh virtualenv` process.
#. In ``virtualenv:<newv>``, change ``virtualenv.version`` to '<newv>rcX', and tag with '<newv>rcX'.
4. Announce ``pip-<newp>rcX`` and ``virtualenv-<newv>rcX`` with the :ref:`RC Install Instructions` and elicit feedback.
5. Apply fixes to 'rcX':
#. Apply fixes to ``pip:<newp>`` and ``virtualenv:<newv>``
#. Periodically merge fixes to ``pip:develop`` and ``virtualenv:develop``
6. Repeat #4 thru #6 if needed.
7. Final Release:
#. In ``pip:<newp>``, change ``pip.version`` to '<newp>', and tag with '<newp>'.
#. Merge ``pip:<newp>`` to ``pip:master``.
#. Build a pip sdist from ``pip:<newp>``, and load it into ``virtualenv:<newv>`` using the :ref:`Refresh virtualenv` process.
#. Merge ``vitualenv:<newv>`` to ``virtualenv:develop``.
#. In ``virtualenv:<newv>``, change ``virtualenv.version`` to '<newv>', and tag with '<newv>'.
#. Merge ``virtualenv:<newp>`` to ``virtualenv:master``
#. Build and upload pip and virtualenv sdists to PyPI.
.. _`Refresh virtualenv`:
Refresh virtualenv
++++++++++++++++++
#. Set the embedded versions of pip, distribute and setuptools in ``bin/refresh-support-files.py``
#. Additionally, set the version of distribute in ``virtualenv_embedded/distribute_setup.py``, and setuptools in ``virtualenv_embedded/ez_setup.py``
#. Run ``bin/refresh-support-files.py`` to download the latest versions.
When specifying a beta of pip not on pypi, the last part of this script will fail. In this case, the pip sdist needs to be placed manually into ``virtualenv_support``.
#. Run ``bin/rebuild-script.py`` to rebuild virtualenv based on the latest versions.
.. _`RC Install Instructions`:
RC Install Instructions
+++++++++++++++++++++++
#. Download and unpack ``https://github.com/pypa/virtualenv/archive/<newv>rcX.tar.gz``
#. Run: ``python virtualenv-<newv>rcX/virtualenv.py myVE``
#. ``myVE/bin/pip`` will be the <newp>rcX version of pip.
pip
===
A tool for installing and managing Python packages.
`Mailing list <http://groups.google.com/group/python-virtualenv>`_ ``|``
`Issues <https://github.com/pypa/pip/issues>`_ ``|``
`Github <https://github.com/pypa/pip>`_ ``|``
`PyPI <https://pypi.python.org/pypi/pip/>`_ ``|``
irc:#pip
.. toctree::
:maxdepth: 2
quickstart
installing
usage
cookbook
logic
configuration
other-tools
development
news
.. _`Installation`:
Installation
============
.. warning::
Prior to version 1.3, pip did not use SSL for downloading packages from PyPI, and thus left
users more vulnerable to security threats. We advise installing at least version 1.3.
If you're using `virtualenv <http://www.virtualenv.org>`_ to install pip, we advise installing
at least version 1.9, which contains pip version 1.3.
Python & OS Support
-------------------
pip works with CPython versions 2.5, 2.6, 2.7, 3.1, 3.2, 3.3 and also pypy.
pip works on Unix/Linux, OS X, and Windows.
Using virtualenv
----------------
The easiest way to install and use pip is with `virtualenv
<http://www.virtualenv.org>`_, since every virtualenv has pip (and it's dependencies) installed into it
automatically.
This does not require root access or modify your system Python
installation. For instance::
$ virtualenv my_env
$ . my_env/bin/activate
(my_env)$ pip install SomePackage
When used in this manner, pip will only affect the active virtual environment.
See the `virtualenv installation instructions <http://www.virtualenv.org/en/latest/#installation>`_.
Installing Globally
-------------------
pip can be installed globally in order to manage global packages.
Often this requires the installation to be performed as root.
.. warning::
We advise against using `easy_install <http://pythonhosted.org/distribute/easy_install.html>`_ to install pip, because easy_install
does not download from PyPI over SSL, so the installation might be insecure.
Since pip can then be used to install packages (which execute code on
your computer), it is better to go through a trusted path.
Requirements
++++++++++++
pip requires either `setuptools <https://pypi.python.org/pypi/setuptools>`_
or `distribute <https://pypi.python.org/pypi/distribute>`_.
See the `Distribute Install Instructions <https://pypi.python.org/pypi/distribute/>`_ or the
`Setuptools Install Instructions <https://pypi.python.org/pypi/setuptools#installation-instructions>`_
If installing pip using a linux package manager, these requirements will be installed for you.
.. warning::
If you are using Python 3.X you **must** use distribute; setuptools doesn't
support Python 3.X.
Using get-pip
+++++++++++++
After installing the requirements:
::
$ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
$ [sudo] python get-pip.py
Installing from source
++++++++++++++++++++++
After installing the requirements:
::
$ curl -O https://pypi.python.org/packages/source/p/pip/pip-X.X.tar.gz
$ tar xvfz pip-X.X.tar.gz
$ cd pip-X.X
$ [sudo] python setup.py install
.. _`pip logic`:
================
Internal Details
================
.. _`Requirements File Format`:
Requirements File Format
========================
Each line of the requirements file indicates something to be installed,
and like arguments to :ref:`pip install`, the following forms are supported::
<requirement specifier>
<archive url/path>
[-e] <local project path>
[-e] <vcs project url>
See the :ref:`pip install Examples<pip install Examples>` for examples of all these forms.
A line beginning with ``#`` is treated as a comment and ignored.
Additionally, the following :ref:`Package Index Options <Package Index Options>` are supported
* :ref:`-i, --index-url <--index-url>`
* :ref:`--extra-index-url <--extra-index-url>`
* :ref:`--no-index <--no-index>`
* :ref:`-f, --find-links <--find-links>`
For example, to specify :ref:`--no-index <--no-index>` and 2 :ref:`--find-links <--find-links>` locations:
::
--no-index
--find-links /my/local/archives
--find-links http://some.archives.com/archives
Lastly, if you wish, you can refer to other requirements files, like this::
-r more_requirements.txt
.. _`Requirement Specifiers`:
Requirement Specifiers
======================
pip supports installing from "requirement specifiers" as implemented in
`pkg_resources Requirements <http://packages.python.org/distribute/pkg_resources.html#requirement-objects>`_
Some Examples::
FooProject >= 1.2
Fizzy [foo, bar]
PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1
SomethingWhoseVersionIDontCareAbout
.. _`VCS Support`:
VCS Support
===========
pip supports installing from Git, Mercurial, Subversion and Bazaar, and detects the type of VCS using url prefixes: "git+", "hg+", "bzr+", "svn+".
pip requires a working VCS command on your path: git, hg, svn, or bzr.
VCS projects can be installed in :ref:`editable mode <editable-installs>` (using the :ref:`--editable <install_--editable>` option) or not.
* For editable installs, the clone location by default is "<venv path>/src/SomeProject" in virtual environments, and "<cwd>/src/SomeProject" for global installs.
The :ref:`--src <install_--src>` option can be used to modify this location.
* For non-editable installs, the project is built locally in a temp dir and then installed normally.
The url suffix "egg=<project name>" is used by pip in it's dependency logic to identify the project prior to pip downloading and analyzing the metadata.
Git
~~~
pip currently supports cloning over ``git``, ``git+http`` and ``git+ssh``::
git+git://git.myproject.org/MyProject#egg=MyProject
git+http://git.myproject.org/MyProject#egg=MyProject
git+ssh://git.myproject.org/MyProject#egg=MyProject
Passing branch names, a commit hash or a tag name is also possible::
git://git.myproject.org/MyProject.git@master#egg=MyProject
git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject
Mercurial
~~~~~~~~~
The supported schemes are: ``hg+http``, ``hg+https``,
``hg+static-http`` and ``hg+ssh``::
hg+http://hg.myproject.org/MyProject#egg=MyProject
hg+https://hg.myproject.org/MyProject#egg=MyProject
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::
hg+http://hg.myproject.org/MyProject@da39a3ee5e6b#egg=MyProject
hg+http://hg.myproject.org/MyProject@2019#egg=MyProject
hg+http://hg.myproject.org/MyProject@v1.0#egg=MyProject
hg+http://hg.myproject.org/MyProject@special_feature#egg=MyProject
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::
svn+svn://svn.myproject.org/svn/MyProject#egg=MyProject
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+...``.
Bazaar
~~~~~~
pip supports Bazaar using the ``bzr+http``, ``bzr+https``, ``bzr+ssh``,
``bzr+sftp``, ``bzr+ftp`` and ``bzr+lp`` schemes::
bzr+http://bzr.myproject.org/MyProject/trunk#egg=MyProject
bzr+sftp://user@myproject.org/MyProject/trunk#egg=MyProject
bzr+ssh://user@myproject.org/MyProject/trunk#egg=MyProject
bzr+ftp://user@myproject.org/MyProject/trunk#egg=MyProject
bzr+lp:MyProject#egg=MyProject
Tags or revisions can be installed like this::
bzr+https://bzr.myproject.org/MyProject/trunk@2019#egg=MyProject
bzr+http://bzr.myproject.org/MyProject/trunk@v1.0#egg=MyProject
Finding Packages
================
pip searches for packages on `PyPI <http://pypi.python.org>`_ using the
`http simple interface <http://pypi.python.org/simple>`_,
which is documented `here <http://packages.python.org/distribute/easy_install.html#package-index-api>`_
and `there <http://www.python.org/dev/peps/pep-0301/>`_
pip offers a set of :ref:`Package Index Options <Package Index Options>` for modifying how packages are found.
See the :ref:`pip install Examples<pip install Examples>`.
.. _`SSL Certificate Verification`:
SSL Certificate Verification
============================
Starting with v1.3, pip provides SSL certificate verification over https, for the purpose
of providing secure, certified downloads from PyPI.
This is supported by default in all Python versions pip supports, except Python 2.5.
Python 2.5 users can :ref:`install an SSL backport <SSL Backport>`, which provides ssl support for older pythons.
Pip does not try to install this automatically because it requires a compiler, which not all systems will have.
Although not recommended, Python 2.5 users who are unable to install ssl, can use the global option,
``--insecure``, to allow access to PyPI w/o attempting SSL certificate verification. This option will only be visible
when ssl is not importable. This is *not* a general option.
.. _`SSL Backport`:
Installing the SSL Backport
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning::
We advise against using ``pip`` itself to install the ssl backport, because it won't be secure
until *after* installing ssl. Likewise, `easy_install <http://pythonhosted.org/distribute/easy_install.html>`_ is not advised, because it
does not currently support ssl.
1. Download the ssl archive:
* Using a Browser:
1. Go to `this url <https://pypi.python.org/pypi/ssl/1.15>`_.
2. Confirm the identity of the site is valid.
Most browsers provide this information to the left of the URL bar in the form of padlock icon that you can click on to confirm the site is verified.
3. Scroll down, and click to download ``ssl-1.15.tar.gz``.
* Using curl, which supports ssl certificate verification:
::
$ curl -O https://pypi.python.org/packages/source/s/ssl/ssl-1.15.tar.gz
2. Confirm the md5sum:
::
$ md5sum ssl-1.15.tar.gz
81ea8a1175e437b4c769ae65b3290e0c ssl-1.15.tar.gz
3. Unpack the archive, and change into the ``ssl-1.15`` directory.
4. Run: ``python setup.py install``.
Hash Verification
=================
PyPI provides md5 hashes in the hash fragment of package download urls.
pip supports checking this, as well as any of the
guaranteed hashlib algorithms (sha1, sha224, sha384, sha256, sha512, md5).
The hash fragment is case sensitive (i.e. sha1 not SHA1).
This check is only intended to provide basic download corruption protection.
It is not intended to provide security against tampering. For that,
see :ref:`SSL Certificate Verification`
Download Cache
==============
pip offers a :ref:`--download-cache <install_--download-cache>` option for installs to prevent redundant downloads of archives from PyPI.
The point of this cache is *not* to circumvent the index crawling process, but to *just* prevent redundant downloads.
Items are stored in this cache based on the url the archive was found at, not simply the archive name.
If you want a fast/local install solution that circumvents crawling PyPI, see the :ref:`Fast & Local Installs` Cookbook entry.
Like all options, :ref:`--download-cache <install_--download-cache>`, can also be set as an environment variable, or placed into the pip config file.
See the :ref:`Configuration` section.
.. _`editable-installs`:
"Editable" Installs
===================
"Editable" installs are fundamentally `"setuptools develop mode" <http://packages.python.org/distribute/setuptools.html#development-mode>`_ installs.
You can install local projects or VCS projects in "editable" mode::
$ pip install -e path/to/SomeProject
$ pip install -e git+http://repo/my_project.git#egg=SomeProject
For local projects, the "SomeProject.egg-info" directory is created relative to the project path.
This is one advantage over just using ``setup.py develop``, which creates the "egg-info" directly relative the current working directory.
setuptools & pkg_resources
==========================
Internally, pip uses the `setuptools` package, and the `pkg_resources` module, which are available from the project, `Setuptools`_, or it's fork `Distribute`_.
pip can work with either `Setuptools`_ or `Distribute`_, although for Python 3, `Distribute`_ is required.
Here are some examples of how pip uses `setuptools` and `pkg_resources`:
* The core of pip's install process uses the `setuptools`'s "install" command.
* Editable ("-e") installs use the `setuptools`'s "develop" command.
* pip uses `pkg_resources` for version parsing, for detecting version conflicts, and to determine what projects are installed,
.. _Setuptools: http://pypi.python.org/pypi/setuptools/0.6c11
.. _Distribute: http://pypi.python.org/pypi/distribute/
========
News
========
Next Release
============
Beta and final releases of 1.3 are planned for Feb 2013.
.. include:: ../CHANGES.txt
===================
Other tools
===================
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
easy_install
------------
pip was originally written to improve on `easy_install <http://pythonhosted.org/distribute/easy_install.html>`_ in the following ways:
* 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 is incompatible with some packages that extensively customize distutils
or setuptools in their ``setup.py`` files.
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.
Quickstart
==========
Install a package:
::
$ pip install SomePackage==1.0
[...]
Successfully installed SomePackage
Show what files were installed:
::
$ pip show --files SomePackage
Name: SomePackage
Version: 1.0
Location: /my/env/lib/pythonx.x/site-packages
Files:
../somepackage/__init__.py
[...]
List what packages are outdated:
::
$ pip list --outdated
SomePackage (Current: 1.0 Latest: 2.0)
Upgrade a package:
::
$ pip install --upgrade SomePackage
[...]
Found existing installation: SomePackage 1.0
Uninstalling SomePackage:
Successfully uninstalled SomePackage
Running setup.py install for SomePackage
Successfully installed SomePackage
Uninstall a package:
::
$ pip uninstall SomePackage
Uninstalling SomePackage:
/my/env/lib/pythonx.x/site-packages/somepackage
Proceed (y/n)? y
Successfully uninstalled SomePackage
==========
Usage
==========
.. _`General Options`:
**General Options:**
.. pip-general-options::
.. _`Package Index Options`:
**Package Index Options:**
.. pip-index-options::
.. _`pip install`:
pip install
-----------
Usage
********
.. pip-command-usage:: install
Description
***********
.. pip-command-description:: install
Options
*******
**Install Options:**
.. pip-command-options:: install
**Other Options:**
* :ref:`Package Index Options <Package Index Options>`
* :ref:`General Options <General Options>`
.. _`pip install Examples`:
Examples
********
1) Install `SomePackage` and it's dependencies from `PyPI`_ using :ref:`Requirement Specifiers`
::
$ pip install SomePackage # latest version
$ pip install SomePackage==1.0.4 # specific version
$ pip install SomePackage>=1.0.4 # minimum version
2) Install a list of requirements specified in a file. See the :ref:`Cookbook entry on Requirements files <Requirements Files>`.
::
$ pip install -r requirements.txt
3) Upgrade an already installed `SomePackage` to the latest from PyPI.
::
$ pip install --upgrade SomePackage
4) Install a local project in "editable" mode. See the section on :ref:`Editable Installs <editable-installs>`.
::
$ pip install -e . # project in current directory
$ pip install -e path/to/project # project in another directory
5) Install a project from VCS in "editable" mode. See the sections on :ref:`VCS Support <VCS Support>` and :ref:`Editable Installs <editable-installs>`.
::
$ pip install -e git+https://git.repo/some_pkg.git#egg=SomePackage # from git
$ pip install -e hg+https://hg.repo/some_pkg.git#egg=SomePackage # from mercurial
$ pip install -e svn+svn://svn.repo/some_pkg/trunk/#egg=SomePackage # from svn
$ pip install -e git+https://git.repo/some_pkg.git@feature#egg=SomePackage # from 'feature' branch
6) Install a package with `setuptools extras`_.
::
$ pip install SomePackage[PDF]
$ pip install SomePackage[PDF]==3.0
$ pip install -e .[PDF]==3.0 # editable project in current directory
7) Install a particular source archive file.
::
$ pip install ./downloads/SomePackage-1.0.4.tar.gz
$ pip install http://my.package.repo/SomePackage-1.0.4.zip
8) Install from alternative package repositories.
Install from a different index, and not `PyPI`_::
$ pip install --index-url http://my.package.repo/simple/ SomePackage
Search an additional index during install, in addition to `PyPI`_::
$ pip install --extra-index-url http://my.package.repo/simple SomePackage
Install from a local flat directory containing archives (and don't scan indexes)::
$ pip install --no-index --find-links:file:///local/dir/ SomePackage
$ pip install --no-index --find-links:/local/dir/ SomePackage
$ pip install --no-index --find-links:relative/dir/ SomePackage
.. _PyPI: http://pypi.python.org/pypi
.. _setuptools extras: http://packages.python.org/distribute/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies
pip uninstall
-------------
Usage
*****
.. pip-command-usage:: uninstall
Description
***********
.. pip-command-description:: uninstall
Options
*******
**Uninstall Options:**
.. pip-command-options:: uninstall
**Other Options:**
* :ref:`General Options <General Options>`
Examples
********
1) Uninstall 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
.. _`pip freeze`:
pip freeze
-----------
Usage
*****
.. pip-command-usage:: freeze
Description
***********
.. pip-command-description:: freeze
Options
*******
**Freeze Options:**
.. pip-command-options:: freeze
**Other Options:**
* :ref:`General Options <General Options>`
Examples
********
1) Generate output suitable for a requirements file.
::
$ pip freeze
Jinja2==2.6
Pygments==1.5
Sphinx==1.1.3
docutils==0.9.1
pip list
---------
Usage
*****
.. pip-command-usage:: list
Description
***********
.. pip-command-description:: list
Options
*******
**List Options:**
.. pip-command-options:: list
**Other Options:**
* :ref:`Package Index Options <Package Index Options>`
* :ref:`General Options <General Options>`
Examples
********
1) List installed packages.
::
$ pip list
Pygments (1.5)
docutils (0.9.1)
Sphinx (1.1.2)
Jinja2 (2.6)
2) List outdated packages (excluding editables), and the latest version available
::
$ pip list --outdated
docutils (Current: 0.9.1 Latest: 0.10)
Sphinx (Current: 1.1.2 Latest: 1.1.3)
pip show
--------
Usage
*****
.. pip-command-usage:: show
Description
***********
.. pip-command-description:: show
Options
*******
**Show Options:**
.. pip-command-options:: show
**Other Options:**
* :ref:`General Options <General Options>`
Examples
********
1. Show information about a package:
::
$ pip show sphinx
---
Name: Sphinx
Version: 1.1.3
Location: /my/env/lib/pythonx.x/site-packages
Requires: Pygments, Jinja2, docutils
pip search
----------
Usage
*****
.. pip-command-usage:: search
Description
***********
.. pip-command-description:: search
Options
*******
**Seach Options:**
.. pip-command-options:: search
**Other Options:**
* :ref:`General Options <General Options>`
Examples
********
1. Search for "peppercorn"
::
$ pip search peppercorn
pepperedform - Helpers for using peppercorn with formprocess.
peppercorn - A library for converting a token stream into [...]
pip zip
-------
Usage
*****
.. pip-command-usage:: zip
Description
***********
.. pip-command-description:: zip
Options
*******
**Zip Options:**
.. pip-command-options:: zip
**Other Options:**
* :ref:`General Options <General Options>`
#!/usr/bin/env python
import os
import optparse
import sys
import re
from pip.exceptions import InstallationError, CommandError, PipError
from pip.log import logger
from pip.util import get_installed_distributions, get_prog
from pip.vcs import git, mercurial, subversion, bazaar # noqa
from pip.baseparser import create_main_parser
from pip.commands import commands, get_similar_commands, get_summaries
# The version as used in the setup.py and the docs conf.py
__version__ = "1.3.1"
def autocomplete():
"""Command and option completion for the main option parser (and options)
and its subcommands (and options).
Enable by sourcing one of the completion shell scripts (bash or zsh).
"""
# Don't complete if user hasn't sourced bash_completion file.
if 'PIP_AUTO_COMPLETE' not in os.environ:
return
cwords = os.environ['COMP_WORDS'].split()[1:]
cword = int(os.environ['COMP_CWORD'])
try:
current = cwords[cword - 1]
except IndexError:
current = ''
subcommands = [cmd for cmd, summary in get_summaries()]
options = []
# subcommand
try:
subcommand_name = [w for w in cwords if w in subcommands][0]
except IndexError:
subcommand_name = None
parser = create_main_parser()
# subcommand options
if subcommand_name:
# special case: 'help' subcommand has no options
if subcommand_name == 'help':
sys.exit(1)
# special case: list locally installed dists for uninstall command
if subcommand_name == 'uninstall' and not current.startswith('-'):
installed = []
lc = current.lower()
for dist in get_installed_distributions(local_only=True):
if dist.key.startswith(lc) and dist.key not in cwords[1:]:
installed.append(dist.key)
# if there are no dists installed, fall back to option completion
if installed:
for dist in installed:
print(dist)
sys.exit(1)
subcommand = commands[subcommand_name](parser)
options += [(opt.get_opt_string(), opt.nargs)
for opt in subcommand.parser.option_list_all
if opt.help != optparse.SUPPRESS_HELP]
# filter out previously specified options from available options
prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
options = [(x, v) for (x, v) in options if x not in prev_opts]
# filter options by current input
options = [(k, v) for k, v in options if k.startswith(current)]
for option in options:
opt_label = option[0]
# append '=' to options which require args
if option[1]:
opt_label += '='
print(opt_label)
else:
# show main parser options only when necessary
if current.startswith('-') or current.startswith('--'):
opts = [i.option_list for i in parser.option_groups]
opts.append(parser.option_list)
opts = (o for it in opts for o in it)
subcommands += [i.get_opt_string() for i in opts
if i.help != optparse.SUPPRESS_HELP]
print(' '.join([x for x in subcommands if x.startswith(current)]))
sys.exit(1)
def parseopts(args):
parser = create_main_parser()
parser.main = True # so the help formatter knows
# create command listing
command_summaries = get_summaries()
description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries]
parser.description = '\n'.join(description)
options, args = parser.parse_args(args)
if options.version:
sys.stdout.write(parser.version)
sys.stdout.write(os.linesep)
sys.exit()
# pip || pip help || pip --help -> print_help()
if not args or (args[0] == 'help' and len(args) == 1):
parser.print_help()
sys.exit()
if not args:
msg = ('You must give a command '
'(use "pip --help" to see a list of commands)')
raise CommandError(msg)
command = args[0].lower()
if command not in commands:
guess = get_similar_commands(command)
msg = ['unknown command "%s"' % command]
if guess:
msg.append('maybe you meant "%s"' % guess)
raise CommandError(' - '.join(msg))
return command, options, args, parser
def main(initial_args=None):
if initial_args is None:
initial_args = sys.argv[1:]
autocomplete()
try:
cmd_name, options, args, parser = parseopts(initial_args)
except PipError:
e = sys.exc_info()[1]
sys.stderr.write("ERROR: %s" % e)
sys.stderr.write(os.linesep)
sys.exit(1)
command = commands[cmd_name](parser) # see baseparser.Command
return command.main(args[1:], options)
def bootstrap():
"""
Bootstrapping function to be called from install-pip.py script.
"""
return main(['install', '--upgrade', 'pip'])
############################################################
## Writing freeze files
class FrozenRequirement(object):
def __init__(self, name, req, editable, comments=()):
self.name = name
self.req = req
self.editable = editable
self.comments = comments
_rev_re = re.compile(r'-r(\d+)$')
_date_re = re.compile(r'-(20\d\d\d\d\d\d)$')
@classmethod
def from_dist(cls, dist, dependency_links, find_tags=False):
location = os.path.normcase(os.path.abspath(dist.location))
comments = []
from pip.vcs import vcs, get_src_requirement
if vcs.get_backend_name(location):
editable = True
try:
req = get_src_requirement(dist, location, find_tags)
except InstallationError:
ex = sys.exc_info()[1]
logger.warn("Error when trying to get requirement for VCS system %s, falling back to uneditable format" % ex)
req = None
if req is None:
logger.warn('Could not determine repository location of %s' % location)
comments.append('## !! Could not determine repository location')
req = dist.as_requirement()
editable = False
else:
editable = False
req = dist.as_requirement()
specs = req.specs
assert len(specs) == 1 and specs[0][0] == '=='
version = specs[0][1]
ver_match = cls._rev_re.search(version)
date_match = cls._date_re.search(version)
if ver_match or date_match:
svn_backend = vcs.get_backend('svn')
if svn_backend:
svn_location = svn_backend(
).get_location(dist, dependency_links)
if not svn_location:
logger.warn(
'Warning: cannot find svn location for %s' % req)
comments.append('## FIXME: could not find svn URL in dependency_links for this package:')
else:
comments.append('# Installing as editable to satisfy requirement %s:' % req)
if ver_match:
rev = ver_match.group(1)
else:
rev = '{%s}' % date_match.group(1)
editable = True
req = '%s@%s#egg=%s' % (svn_location, rev, cls.egg_name(dist))
return cls(dist.project_name, req, editable, comments)
@staticmethod
def egg_name(dist):
name = dist.egg_name()
match = re.search(r'-py\d\.\d$', name)
if match:
name = name[:match.start()]
return name
def __str__(self):
req = self.req
if self.editable:
req = '-e %s' % req
return '\n'.join(list(self.comments) + [str(req)]) + '\n'
if __name__ == '__main__':
exit = main()
if exit:
sys.exit(exit)
import sys
from .runner import run
if __name__ == '__main__':
exit = run()
if exit:
sys.exit(exit)
"""Stuff that differs in different Python versions"""
import os
import imp
import sys
import site
__all__ = ['WindowsError']
uses_pycache = hasattr(imp, 'cache_from_source')
class NeverUsedException(Exception):
"""this exception should never be raised"""
try:
WindowsError = WindowsError
except NameError:
WindowsError = NeverUsedException
try:
#new in Python 3.3
PermissionError = PermissionError
except NameError:
PermissionError = NeverUsedException
console_encoding = sys.__stdout__.encoding
if sys.version_info >= (3,):
from io import StringIO, BytesIO
from functools import reduce
from urllib.error import URLError, HTTPError
from queue import Queue, Empty
from urllib.request import url2pathname
from urllib.request import urlretrieve
from email import message as emailmessage
import urllib.parse as urllib
import urllib.request as urllib2
import configparser as ConfigParser
import xmlrpc.client as xmlrpclib
import urllib.parse as urlparse
import http.client as httplib
def cmp(a, b):
return (a > b) - (a < b)
def b(s):
return s.encode('utf-8')
def u(s):
return s.decode('utf-8')
def console_to_str(s):
try:
return s.decode(console_encoding)
except UnicodeDecodeError:
return s.decode('utf_8')
def fwrite(f, s):
f.buffer.write(b(s))
bytes = bytes
string_types = (str,)
raw_input = input
else:
from cStringIO import StringIO
from urllib2 import URLError, HTTPError
from Queue import Queue, Empty
from urllib import url2pathname, urlretrieve
from email import Message as emailmessage
import urllib
import urllib2
import urlparse
import ConfigParser
import xmlrpclib
import httplib
def b(s):
return s
def u(s):
return s
def console_to_str(s):
return s
def fwrite(f, s):
f.write(s)
bytes = str
string_types = (basestring,)
reduce = reduce
cmp = cmp
raw_input = raw_input
BytesIO = StringIO
from distutils.sysconfig import get_python_lib, get_python_version
#site.USER_SITE was created in py2.6
user_site = getattr(site, 'USER_SITE', None)
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = list(map(tuple, args)) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x + [y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
def home_lib(home):
"""Return the lib dir under the 'home' installation scheme"""
if hasattr(sys, 'pypy_version_info'):
lib = 'site-packages'
else:
lib = os.path.join('lib', 'python')
return os.path.join(home, lib)
## py25 has no builtin ssl module
## only >=py32 has ssl.match_hostname and ssl.CertificateError
try:
import ssl
try:
from ssl import match_hostname, CertificateError
except ImportError:
from pip.backwardcompat.ssl_match_hostname import match_hostname, CertificateError
except ImportError:
ssl = None
# patch for py25 socket to work with http://pypi.python.org/pypi/ssl/
import socket
if not hasattr(socket, 'create_connection'): # for Python 2.5
# monkey-patch socket module
from pip.backwardcompat.socket_create_connection import create_connection
socket.create_connection = create_connection
"""
patch for py25 socket to work with http://pypi.python.org/pypi/ssl/
copy-paste from py2.6 stdlib socket.py
https://gist.github.com/zed/1347055
"""
import socket
import sys
_GLOBAL_DEFAULT_TIMEOUT = getattr(socket, '_GLOBAL_DEFAULT_TIMEOUT', object())
def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
source_address=None):
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`getdefaulttimeout`
is used.
"""
host, port = address
err = None
for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
sock.connect(sa)
return sock
except socket.error:
err = sys.exc_info()[1]
if sock is not None:
sock.close()
if err is not None:
raise err
else:
raise socket.error("getaddrinfo returns an empty list")
"""The match_hostname() function from Python 3.2, essential when using SSL."""
import re
__version__ = '3.2a3'
class CertificateError(ValueError):
pass
def _dnsname_to_pat(dn):
pats = []
for frag in dn.split(r'.'):
if frag == '*':
# When '*' is a fragment by itself, it matches a non-empty dotless
# fragment.
pats.append('[^.]+')
else:
# Otherwise, '*' matches any dotless fragment.
frag = re.escape(frag)
pats.append(frag.replace(r'\*', '[^.]*'))
return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
def match_hostname(cert, hostname):
"""Verify that *cert* (in decoded format as returned by
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules
are mostly followed, but IP addresses are not accepted for *hostname*.
CertificateError is raised on failure. On success, the function
returns nothing.
"""
if not cert:
raise ValueError("empty or no certificate")
dnsnames = []
san = cert.get('subjectAltName', ())
for key, value in san:
if key == 'DNS':
if _dnsname_to_pat(value).match(hostname):
return
dnsnames.append(value)
if not san:
# The subject is only checked when subjectAltName is empty
for sub in cert.get('subject', ()):
for key, value in sub:
# XXX according to RFC 2818, the most specific Common Name
# must be used.
if key == 'commonName':
if _dnsname_to_pat(value).match(hostname):
return
dnsnames.append(value)
if len(dnsnames) > 1:
raise CertificateError("hostname %r "
"doesn't match either of %s"
% (hostname, ', '.join(map(repr, dnsnames))))
elif len(dnsnames) == 1:
raise CertificateError("hostname %r "
"doesn't match %r"
% (hostname, dnsnames[0]))
else:
raise CertificateError("no appropriate commonName or "
"subjectAltName fields were found")
"""Base Command class, and related routines"""
import os
import socket
import sys
import tempfile
import traceback
import time
import optparse
from pip.log import logger
from pip.download import urlopen
from pip.exceptions import (BadCommand, InstallationError, UninstallationError,
CommandError)
from pip.backwardcompat import StringIO, ssl
from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
from pip.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND
from pip.util import get_prog
__all__ = ['Command']
# for backwards compatibiliy
get_proxy = urlopen.get_proxy
class Command(object):
name = None
usage = None
hidden = False
def __init__(self, main_parser):
parser_kw = {
'usage': self.usage,
'prog': '%s %s' % (get_prog(), self.name),
'formatter': UpdatingDefaultsHelpFormatter(),
'add_help_option': False,
'name': self.name,
'description': self.__doc__,
}
self.main_parser = main_parser
self.parser = ConfigOptionParser(**parser_kw)
# Commands should add options to this option group
optgroup_name = '%s Options' % self.name.capitalize()
self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name)
# Re-add all options and option groups.
for group in main_parser.option_groups:
self._copy_option_group(self.parser, group)
# Copies all general options from the main parser.
self._copy_options(self.parser, main_parser.option_list)
def _copy_options(self, parser, options):
"""Populate an option parser or group with options."""
for option in options:
if not option.dest:
continue
parser.add_option(option)
def _copy_option_group(self, parser, group):
"""Copy option group (including options) to another parser."""
new_group = optparse.OptionGroup(parser, group.title)
self._copy_options(new_group, group.option_list)
parser.add_option_group(new_group)
def merge_options(self, initial_options, options):
# Make sure we have all global options carried over
attrs = ['log', 'proxy', 'require_venv',
'log_explicit_levels', 'log_file',
'timeout', 'default_vcs',
'skip_requirements_regex',
'no_input', 'exists_action',
'cert']
if not ssl:
attrs.append('insecure')
for attr in attrs:
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()
#TODO: try to get these passing down from the command?
# without resorting to os.environ to hold these.
if options.no_input:
os.environ['PIP_NO_INPUT'] = '1'
if options.exists_action:
os.environ['PIP_EXISTS_ACTION'] = ''.join(options.exists_action)
if not ssl and options.insecure:
os.environ['PIP_INSECURE'] = '1'
if options.cert:
os.environ['PIP_CERT'] = options.cert
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)
try:
log_fp = open_logfile(log_fn, 'w')
except IOError:
temp = tempfile.NamedTemporaryFile(delete=False)
log_fn = temp.name
log_fp = open_logfile(log_fn, 'w')
logger.fatal('Storing complete log in %s' % log_fn)
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
This diff is collapsed.
This diff is collapsed.
"""shared options and groups"""
from optparse import make_option, OptionGroup
def make_option_group(group, parser):
"""
Return an OptionGroup object
group -- assumed to be dict with 'name' and 'options' keys
parser -- an optparse Parser
"""
option_group = OptionGroup(parser, group['name'])
for option in group['options']:
option_group.add_option(option)
return option_group
###########
# options #
###########
index_url = make_option(
'-i', '--index-url', '--pypi-url',
dest='index_url',
metavar='URL',
default='https://pypi.python.org/simple/',
help='Base URL of Python Package Index (default %default).')
extra_index_url = make_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.')
no_index = make_option(
'--no-index',
dest='no_index',
action='store_true',
default=False,
help='Ignore package index (only looking at --find-links URLs instead).')
find_links = make_option(
'-f', '--find-links',
dest='find_links',
action='append',
default=[],
metavar='url',
help="If a url or path to an html file, then parse for links to archives. If a local path or file:// url that's a directory, then look for archives in the directory listing.")
use_mirrors = make_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.')
mirrors = make_option(
'--mirrors',
dest='mirrors',
metavar='URL',
action='append',
default=[],
help='Specific mirror URLs to query when --use-mirrors is used.')
##########
# groups #
##########
index_group = {
'name': 'Package Index Options',
'options': [
index_url,
extra_index_url,
no_index,
find_links,
use_mirrors,
mirrors
]
}
"""
Package containing all pip commands
"""
from pip.commands.bundle import BundleCommand
from pip.commands.completion import CompletionCommand
from pip.commands.freeze import FreezeCommand
from pip.commands.help import HelpCommand
from pip.commands.list import ListCommand
from pip.commands.search import SearchCommand
from pip.commands.show import ShowCommand
from pip.commands.install import InstallCommand
from pip.commands.uninstall import UninstallCommand
from pip.commands.unzip import UnzipCommand
from pip.commands.zip import ZipCommand
commands = {
BundleCommand.name: BundleCommand,
CompletionCommand.name: CompletionCommand,
FreezeCommand.name: FreezeCommand,
HelpCommand.name: HelpCommand,
SearchCommand.name: SearchCommand,
ShowCommand.name: ShowCommand,
InstallCommand.name: InstallCommand,
UninstallCommand.name: UninstallCommand,
UnzipCommand.name: UnzipCommand,
ZipCommand.name: ZipCommand,
ListCommand.name: ListCommand,
}
commands_order = [
InstallCommand,
UninstallCommand,
FreezeCommand,
ListCommand,
ShowCommand,
SearchCommand,
ZipCommand,
UnzipCommand,
BundleCommand,
HelpCommand,
]
def get_summaries(ignore_hidden=True, ordered=True):
"""Yields sorted (command name, command summary) tuples."""
if ordered:
cmditems = _sort_commands(commands, commands_order)
else:
cmditems = commands.items()
for name, command_class in cmditems:
if ignore_hidden and command_class.hidden:
continue
yield (name, command_class.summary)
def get_similar_commands(name):
"""Command name auto-correct."""
from difflib import get_close_matches
close_commands = get_close_matches(name, commands.keys())
if close_commands:
guess = close_commands[0]
else:
guess = False
return guess
def _sort_commands(cmddict, order):
def keyfn(key):
try:
return order.index(key[1])
except ValueError:
# unordered items should come last
return 0xff
return sorted(cmddict.items(), key=keyfn)
from pip.locations import build_prefix, src_prefix
from pip.util import display_path, backup_dir
from pip.log import logger
from pip.exceptions import InstallationError
from pip.commands.install import InstallCommand
class BundleCommand(InstallCommand):
"""Create pybundles (archives containing multiple packages)."""
name = 'bundle'
usage = """
%prog [options] <bundle name>.pybundle <package>..."""
summary = 'Create pybundles.'
bundle = True
def __init__(self, *args, **kw):
super(BundleCommand, self).__init__(*args, **kw)
# bundle uses different default source and build dirs
build_opt = self.parser.get_option("--build")
build_opt.default = backup_dir(build_prefix, '-bundle')
src_opt = self.parser.get_option("--src")
src_opt.default = backup_dir(src_prefix, '-bundle')
self.parser.set_defaults(**{
src_opt.dest: src_opt.default,
build_opt.dest: build_opt.default,
})
def run(self, options, args):
if not args:
raise InstallationError('You must give a bundle filename')
# We have to get everything when creating a bundle:
options.ignore_installed = True
logger.notify('Putting temporary build files in %s and source/develop files in %s'
% (display_path(options.build_dir), display_path(options.src_dir)))
self.bundle_filename = args.pop(0)
requirement_set = super(BundleCommand, self).run(options, args)
return requirement_set
import sys
from pip.basecommand import Command
BASE_COMPLETION = """
# pip %(shell)s completion start%(script)s# pip %(shell)s completion end
"""
COMPLETION_SCRIPTS = {
'bash': """
_pip_completion()
{
COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\
COMP_CWORD=$COMP_CWORD \\
PIP_AUTO_COMPLETE=1 $1 ) )
}
complete -o default -F _pip_completion pip
""", 'zsh': """
function _pip_completion {
local words cword
read -Ac words
read -cn cword
reply=( $( COMP_WORDS="$words[*]" \\
COMP_CWORD=$(( cword-1 )) \\
PIP_AUTO_COMPLETE=1 $words[1] ) )
}
compctl -K _pip_completion pip
"""}
class CompletionCommand(Command):
"""A helper command to be used for command completion."""
name = 'completion'
summary = 'A helper command to be used for command completion'
hidden = True
def __init__(self, *args, **kw):
super(CompletionCommand, self).__init__(*args, **kw)
self.parser.add_option(
'--bash', '-b',
action='store_const',
const='bash',
dest='shell',
help='Emit completion code for bash')
self.parser.add_option(
'--zsh', '-z',
action='store_const',
const='zsh',
dest='shell',
help='Emit completion code for zsh')
def run(self, options, args):
"""Prints the completion code of the given shell"""
shells = COMPLETION_SCRIPTS.keys()
shell_options = ['--' + shell for shell in sorted(shells)]
if options.shell in shells:
script = COMPLETION_SCRIPTS.get(options.shell, '')
print(BASE_COMPLETION % {'script': script, 'shell': options.shell})
else:
sys.stderr.write('ERROR: You must pass %s\n' % ' or '.join(shell_options))
import re
import sys
import pkg_resources
import pip
from pip.req import InstallRequirement
from pip.log import logger
from pip.basecommand import Command
from pip.util import get_installed_distributions
class FreezeCommand(Command):
"""Output installed packages in requirements format."""
name = 'freeze'
usage = """
%prog [options]"""
summary = 'Output installed packages in requirements format.'
def __init__(self, *args, **kw):
super(FreezeCommand, self).__init__(*args, **kw)
self.cmd_opts.add_option(
'-r', '--requirement',
dest='requirement',
action='store',
default=None,
metavar='file',
help="Use the order in the given requirements file and it's comments when generating output.")
self.cmd_opts.add_option(
'-f', '--find-links',
dest='find_links',
action='append',
default=[],
metavar='URL',
help='URL for finding packages, which will be added to the output.')
self.cmd_opts.add_option(
'-l', '--local',
dest='local',
action='store_true',
default=False,
help='If in a virtualenv that has global access, do not output globally-installed packages.')
self.parser.insert_option_group(0, self.cmd_opts)
def setup_logging(self):
logger.move_stdout_to_stderr()
def run(self, options, args):
requirement = options.requirement
find_links = options.find_links or []
local_only = options.local
## FIXME: Obviously this should be settable:
find_tags = False
skip_match = None
skip_regex = options.skip_requirements_regex
if skip_regex:
skip_match = re.compile(skip_regex)
dependency_links = []
f = sys.stdout
for dist in pkg_resources.working_set:
if dist.has_metadata('dependency_links.txt'):
dependency_links.extend(dist.get_metadata_lines('dependency_links.txt'))
for link in find_links:
if '#egg=' in link:
dependency_links.append(link)
for link in find_links:
f.write('-f %s\n' % link)
installations = {}
for dist in get_installed_distributions(local_only=local_only):
req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
installations[req.name] = req
if requirement:
req_f = open(requirement)
for line in req_f:
if not line.strip() or line.strip().startswith('#'):
f.write(line)
continue
if skip_match and skip_match.search(line):
f.write(line)
continue
elif line.startswith('-e') or line.startswith('--editable'):
if line.startswith('-e'):
line = line[2:].strip()
else:
line = line[len('--editable'):].strip().lstrip('=')
line_req = InstallRequirement.from_editable(line, default_vcs=options.default_vcs)
elif (line.startswith('-r') or line.startswith('--requirement')
or line.startswith('-Z') or line.startswith('--always-unzip')
or line.startswith('-f') or line.startswith('-i')
or line.startswith('--extra-index-url')
or line.startswith('--find-links')
or line.startswith('--index-url')):
f.write(line)
continue
else:
line_req = InstallRequirement.from_line(line)
if not line_req.name:
logger.notify("Skipping line because it's not clear what it would install: %s"
% line.strip())
logger.notify(" (add #egg=PackageName to the URL to avoid this warning)")
continue
if line_req.name not in installations:
logger.warn("Requirement file contains %s, but that package is not installed"
% line.strip())
continue
f.write(str(installations[line_req.name]))
del installations[line_req.name]
f.write('## The following requirements were added by pip --freeze:\n')
for installation in sorted(installations.values(), key=lambda x: x.name):
f.write(str(installation))
from pip.basecommand import Command, SUCCESS
from pip.exceptions import CommandError
class HelpCommand(Command):
"""Show help for commands"""
name = 'help'
usage = """
%prog <command>"""
summary = 'Show help for commands.'
def run(self, options, args):
from pip.commands import commands, get_similar_commands
try:
# 'pip help' with no args is handled by pip.__init__.parseopt()
cmd_name = args[0] # the command we need help for
except IndexError:
return SUCCESS
if cmd_name not in commands:
guess = get_similar_commands(cmd_name)
msg = ['unknown command "%s"' % cmd_name]
if guess:
msg.append('maybe you meant "%s"' % guess)
raise CommandError(' - '.join(msg))
command = commands[cmd_name](self.main_parser) # instantiate
command.parser.print_help()
return SUCCESS
This diff is collapsed.
from pip.basecommand import Command
from pip.exceptions import DistributionNotFound, BestVersionAlreadyInstalled
from pip.index import PackageFinder
from pip.log import logger
from pip.req import InstallRequirement
from pip.util import get_installed_distributions, dist_is_editable
from pip.cmdoptions import make_option_group, index_group
class ListCommand(Command):
"""List installed packages, including editables."""
name = 'list'
usage = """
%prog [options]"""
summary = 'List installed packages.'
def __init__(self, *args, **kw):
super(ListCommand, self).__init__(*args, **kw)
cmd_opts = self.cmd_opts
cmd_opts.add_option(
'-o', '--outdated',
action='store_true',
default=False,
help='List outdated packages (excluding editables)')
cmd_opts.add_option(
'-u', '--uptodate',
action='store_true',
default=False,
help='List uptodate packages (excluding editables)')
cmd_opts.add_option(
'-e', '--editable',
action='store_true',
default=False,
help='List editable projects.')
cmd_opts.add_option(
'-l', '--local',
action='store_true',
default=False,
help='If in a virtualenv that has global access, do not list globally-installed packages.')
index_opts = make_option_group(index_group, self.parser)
self.parser.insert_option_group(0, index_opts)
self.parser.insert_option_group(0, cmd_opts)
def _build_package_finder(self, options, index_urls):
"""
Create a package finder appropriate to this list command.
"""
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.outdated:
self.run_outdated(options)
elif options.uptodate:
self.run_uptodate(options)
elif options.editable:
self.run_editables(options)
else:
self.run_listing(options)
def run_outdated(self, options):
for dist, remote_version_raw, remote_version_parsed in self.find_packages_latests_versions(options):
if remote_version_parsed > dist.parsed_version:
logger.notify('%s (Current: %s Latest: %s)' % (dist.project_name,
dist.version, remote_version_raw))
def find_packages_latests_versions(self, options):
index_urls = [options.index_url] + options.extra_index_urls
if options.no_index:
logger.notify('Ignoring indexes: %s' % ','.join(index_urls))
index_urls = []
dependency_links = []
for dist in get_installed_distributions(local_only=options.local):
if dist.has_metadata('dependency_links.txt'):
dependency_links.extend(
dist.get_metadata_lines('dependency_links.txt'),
)
finder = self._build_package_finder(options, index_urls)
finder.add_dependency_links(dependency_links)
installed_packages = get_installed_distributions(local_only=options.local, include_editables=False)
for dist in installed_packages:
req = InstallRequirement.from_line(dist.key, None)
try:
link = finder.find_requirement(req, True)
# If link is None, means installed version is most up-to-date
if link is None:
continue
except DistributionNotFound:
continue
except BestVersionAlreadyInstalled:
remote_version = req.installed_version
else:
# It might be a good idea that link or finder had a public method
# that returned version
remote_version = finder._link_package_versions(link, req.name)[0]
remote_version_raw = remote_version[2]
remote_version_parsed = remote_version[0]
yield dist, remote_version_raw, remote_version_parsed
def run_listing(self, options):
installed_packages = get_installed_distributions(local_only=options.local)
self.output_package_listing(installed_packages)
def run_editables(self, options):
installed_packages = get_installed_distributions(local_only=options.local, editables_only=True)
self.output_package_listing(installed_packages)
def output_package_listing(self, installed_packages):
installed_packages = sorted(installed_packages, key=lambda dist: dist.project_name.lower())
for dist in installed_packages:
if dist_is_editable(dist):
line = '%s (%s, %s)' % (dist.project_name, dist.version, dist.location)
else:
line = '%s (%s)' % (dist.project_name, dist.version)
logger.notify(line)
def run_uptodate(self, options):
uptodate = []
for dist, remote_version_raw, remote_version_parsed in self.find_packages_latests_versions(options):
if dist.parsed_version == remote_version_parsed:
uptodate.append(dist)
self.output_package_listing(uptodate)
import sys
import textwrap
import pkg_resources
import pip.download
from pip.basecommand import Command, SUCCESS
from pip.util import get_terminal_size
from pip.log import logger
from pip.backwardcompat import xmlrpclib, reduce, cmp
from pip.exceptions import CommandError
from pip.status_codes import NO_MATCHES_FOUND
from distutils.version import StrictVersion, LooseVersion
class SearchCommand(Command):
"""Search for PyPI packages whose name or summary contains <query>."""
name = 'search'
usage = """
%prog [options] <query>"""
summary = 'Search PyPI for packages.'
def __init__(self, *args, **kw):
super(SearchCommand, self).__init__(*args, **kw)
self.cmd_opts.add_option(
'--index',
dest='index',
metavar='URL',
default='https://pypi.python.org/pypi',
help='Base URL of Python Package Index (default %default)')
self.parser.insert_option_group(0, self.cmd_opts)
def run(self, options, args):
if not args:
raise CommandError('Missing required argument (search query).')
query = args
index_url = options.index
pypi_hits = self.search(query, index_url)
hits = transform_hits(pypi_hits)
terminal_width = None
if sys.stdout.isatty():
terminal_width = get_terminal_size()[0]
print_results(hits, terminal_width=terminal_width)
if pypi_hits:
return SUCCESS
return NO_MATCHES_FOUND
def search(self, query, index_url):
pypi = xmlrpclib.ServerProxy(index_url, pip.download.xmlrpclib_transport)
hits = pypi.search({'name': query, 'summary': query}, 'or')
return hits
def transform_hits(hits):
"""
The list from pypi is really a list of versions. We want a list of
packages with the list of versions stored inline. This converts the
list from pypi into one we can use.
"""
packages = {}
for hit in hits:
name = hit['name']
summary = hit['summary']
version = hit['version']
score = hit['_pypi_ordering']
if score is None:
score = 0
if name not in packages.keys():
packages[name] = {'name': name, 'summary': summary, 'versions': [version], 'score': score}
else:
packages[name]['versions'].append(version)
# if this is the highest version, replace summary and score
if version == highest_version(packages[name]['versions']):
packages[name]['summary'] = summary
packages[name]['score'] = score
# each record has a unique name now, so we will convert the dict into a list sorted by score
package_list = sorted(packages.values(), key=lambda x: x['score'], reverse=True)
return package_list
def print_results(hits, name_column_width=25, terminal_width=None):
installed_packages = [p.project_name for p in pkg_resources.working_set]
for hit in hits:
name = hit['name']
summary = hit['summary'] or ''
if terminal_width is not None:
# wrap and indent summary to fit terminal
summary = textwrap.wrap(summary, terminal_width - name_column_width - 5)
summary = ('\n' + ' ' * (name_column_width + 3)).join(summary)
line = '%s - %s' % (name.ljust(name_column_width), summary)
try:
logger.notify(line)
if name in installed_packages:
dist = pkg_resources.get_distribution(name)
logger.indent += 2
try:
latest = highest_version(hit['versions'])
if dist.version == latest:
logger.notify('INSTALLED: %s (latest)' % dist.version)
else:
logger.notify('INSTALLED: %s' % dist.version)
logger.notify('LATEST: %s' % latest)
finally:
logger.indent -= 2
except UnicodeEncodeError:
pass
def compare_versions(version1, version2):
try:
return cmp(StrictVersion(version1), StrictVersion(version2))
# in case of abnormal version number, fall back to LooseVersion
except ValueError:
pass
try:
return cmp(LooseVersion(version1), LooseVersion(version2))
except TypeError:
# certain LooseVersion comparions raise due to unorderable types,
# fallback to string comparison
return cmp([str(v) for v in LooseVersion(version1).version],
[str(v) for v in LooseVersion(version2).version])
def highest_version(versions):
return reduce((lambda v1, v2: compare_versions(v1, v2) == 1 and v1 or v2), versions)
import os
import pkg_resources
from pip.basecommand import Command
from pip.log import logger
class ShowCommand(Command):
"""Show information about one or more installed packages."""
name = 'show'
usage = """
%prog [options] <package> ..."""
summary = 'Show information about installed packages.'
def __init__(self, *args, **kw):
super(ShowCommand, self).__init__(*args, **kw)
self.cmd_opts.add_option(
'-f', '--files',
dest='files',
action='store_true',
default=False,
help='Show the full list of installed files for each package.')
self.parser.insert_option_group(0, self.cmd_opts)
def run(self, options, args):
if not args:
logger.warn('ERROR: Please provide a package name or names.')
return
query = args
results = search_packages_info(query)
print_results(results, options.files)
def search_packages_info(query):
"""
Gather details from installed distributions. Print distribution name,
version, location, and installed files. Installed files requires a
pip generated 'installed-files.txt' in the distributions '.egg-info'
directory.
"""
installed_packages = dict(
[(p.project_name.lower(), p) for p in pkg_resources.working_set])
for name in query:
normalized_name = name.lower()
if normalized_name in installed_packages:
dist = installed_packages[normalized_name]
package = {
'name': dist.project_name,
'version': dist.version,
'location': dist.location,
'requires': [dep.project_name for dep in dist.requires()],
}
filelist = os.path.join(
dist.location,
dist.egg_name() + '.egg-info',
'installed-files.txt')
if os.path.isfile(filelist):
package['files'] = filelist
yield package
def print_results(distributions, list_all_files):
"""
Print the informations from installed distributions found.
"""
for dist in distributions:
logger.notify("---")
logger.notify("Name: %s" % dist['name'])
logger.notify("Version: %s" % dist['version'])
logger.notify("Location: %s" % dist['location'])
logger.notify("Requires: %s" % ', '.join(dist['requires']))
if list_all_files:
logger.notify("Files:")
if 'files' in dist:
for line in open(dist['files']):
logger.notify(" %s" % line.strip())
else:
logger.notify("Cannot locate installed-files.txt")
This diff is collapsed.
from pip.commands.zip import ZipCommand
class UnzipCommand(ZipCommand):
"""Unzip individual packages."""
name = 'unzip'
summary = 'Unzip individual packages.'
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
SUCCESS = 0
ERROR = 1
UNKNOWN_ERROR = 2
VIRTUALENV_NOT_FOUND = 3
NO_MATCHES_FOUND = 23
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment