A command line utility to display dependency tree of the installed Python packages
Go to file
Vineet Naik 8db536eab3 Majorly refactor the code
The primary reason behind refactoring the code is to be able to make it
straightforward to implement the --reverse mode (ie. instead of showing
package and their sub-deps, it will show the sub-deps and the packages
that need them).

As a part of this change, wrapper classes have been added for
Distribution and Requirements instances that pip returns. These wrapper
classes have handle the rendering of the pkg as a root (top level) and a
branch (non-top level) accordingly. As a result the same function
`render_tree` can be used for --reverse mode.

This change doesn't include the --reverse mode implementation. It will
be added in the subsequent commit.
2015-11-09 00:32:39 +05:30
tests Majorly refactor the code 2015-11-09 00:32:39 +05:30
.gitignore Resolve merge conflicts 2014-06-14 23:44:16 +05:30
.travis.yml Migrate travis builds to container-based infra 2015-07-30 00:23:10 +05:30
CHANGES.md Bump version to 0.4.3 and add changelog 2015-08-03 21:38:39 +05:30
LICENSE Update year in license 2015-07-26 23:24:32 +05:30
MANIFEST.in Include license and changelog in dist tar ball 2015-07-26 23:26:35 +05:30
Makefile Modify test workflow 2015-07-30 00:07:15 +05:30
README.rst Update README 2015-08-03 22:09:14 +05:30
pipdeptree.py Majorly refactor the code 2015-11-09 00:32:39 +05:30
pytest.ini Switch from nose to pytest 2014-06-12 15:55:52 -07:00
setup.py Add __version__ attr to pipdeptree module 2015-08-03 21:26:02 +05:30
tox.ini Modify test workflow 2015-07-30 00:07:15 +05:30

README.rst

pipdeptree
==========

.. image:: https://travis-ci.org/naiquevin/pipdeptree.svg?branch=master
   :target: https://travis-ci.org/naiquevin/pipdeptree


``pipdeptree`` is a command line utility for displaying the python
packages installed in an virtualenv in form of a dependency
tree. Since ``pip freeze`` shows all dependencies as a flat list,
finding out which are the top level packages and which packages do
they depend on requires some effort. It can also be tedious to resolve
conflicting dependencies because ``pip`` doesn't yet have true
dependency resolution (more on this later). This utility tries to
solve these problem.

To some extent, this tool is inspired by ``lein deps :tree`` command
of `Leiningen <http://leiningen.org/>`_.


Installation
------------

.. code-block:: bash

    $ pip install pipdeptree


Usage and examples
------------------

To give you a brief idea, here is the output of ``pipdeptree``
compared with ``pip freeze``:

.. code-block:: bash

    $ pip freeze
    Flask==0.10.1
    Flask-Script==0.6.6
    Jinja2==2.7.2
    -e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy-master
    Mako==0.9.1
    MarkupSafe==0.18
    SQLAlchemy==0.9.1
    Werkzeug==0.9.4
    alembic==0.6.2
    argparse==1.2.1
    ipython==2.0.0
    itsdangerous==0.23
    psycopg2==2.5.2
    redis==2.9.1
    slugify==0.0.1
    wsgiref==0.1.2

And now see what ``pipdeptree`` outputs,

.. code-block:: bash

    $ pipdeptree
    Warning!!! Possible confusing dependencies found:
    * Mako==0.9.1 -> MarkupSafe [required: >=0.9.2, installed: 0.18]
      Jinja2==2.7.2 -> MarkupSafe [installed: 0.18]
    ------------------------------------------------------------------------
    Lookupy==0.1
    wsgiref==0.1.2
    argparse==1.2.1
    psycopg2==2.5.2
    Flask-Script==0.6.6
      - Flask [installed: 0.10.1]
        - Werkzeug [required: >=0.7, installed: 0.9.4]
        - Jinja2 [required: >=2.4, installed: 2.7.2]
          - MarkupSafe [installed: 0.18]
        - itsdangerous [required: >=0.21, installed: 0.23]
    alembic==0.6.2
      - SQLAlchemy [required: >=0.7.3, installed: 0.9.1]
      - Mako [installed: 0.9.1]
        - MarkupSafe [required: >=0.9.2, installed: 0.18]
    ipython==2.0.0
    slugify==0.0.1
    redis==2.9.1


What's with the warning about confusing dependencies?
-----------------------------------------------------

As seen in the above output, ``pipdeptree`` by default warns about
possible confusing dependencies. Any package that's specified as a
dependency of multiple packages with a different version is considered
as a possible confusing dependency. This is helpful because ``pip``
`doesn't have true dependency resolution
<https://github.com/pypa/pip/issues/988>`_ yet. The warning is printed
to stderr instead of stdout and it can be completely disabled by using
the ``--nowarn`` flag.


Warnings about circular dependencies
------------------------------------

In case any of the packages have circular dependencies (eg. package A
depending upon package B and package B depending upon package A), then
``pipdeptree`` will print warnings about that as well.

.. code-block:: bash

    $ pipdeptree
    Warning!!! Cyclic dependencies found:
    - CircularDependencyA => CircularDependencyB => CircularDependencyA
    - CircularDependencyB => CircularDependencyA => CircularDependencyB
    ------------------------------------------------------------------------
    wsgiref==0.1.2
    argparse==1.2.1

As with the confusing dependencies warnings, these are printed to
stderr and can be disabled using the ``--nowarn`` flag.


Using pipdeptree to write requirements.txt file
-----------------------------------------------

If you wish to track only the top level packages in your
``requirements.txt`` file, it's possible to do so using ``pipdeptree``
by grep-ing only the top-level lines from the output,

.. code-block:: bash

    $ pipdeptree | grep -P '^\w+'
    Lookupy==0.1
    wsgiref==0.1.2
    argparse==1.2.1
    psycopg2==2.5.2
    Flask-Script==0.6.6
    alembic==0.6.2
    ipython==2.0.0
    slugify==0.0.1
    redis==2.9.1

There is a problem here though. The output doesn't mention anything
about ``Lookupy`` being installed as an editable package (refer to the
output of ``pip freeze`` above) and information about it's source is
lost. To fix this, ``pipdeptree`` must be run with a ``-f`` or
``--freeze`` flag.

.. code-block:: bash

    $ pipdeptree -f --nowarn | grep -P '^[\w0-9\-=.]+'
    -e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy-master
    wsgiref==0.1.2
    argparse==1.2.1
    psycopg2==2.5.2
    Flask-Script==0.6.6
    alembic==0.6.2
    ipython==2.0.0
    slugify==0.0.1
    redis==2.9.1

    $ pipdeptree -f --nowarn | grep -P '^[\w0-9\-=.]+' > requirements.txt

The freeze flag will also not output the hyphens for child
dependencies, so you could dump the complete output of ``pipdeptree
-f`` to the requirements.txt file making the file human-friendly (due
to indentations) as well as pip-friendly. (Take care of duplicate
dependencies though)


Usage
-----

.. code-block:: bash

    usage: pipdeptree.py [-h] [-f] [-a] [-l] [-w]

    Dependency tree of the installed python packages

    optional arguments:
      -h, --help        show this help message and exit
      -f, --freeze      Print names so as to write freeze files
      -a, --all         list all deps at top level
      -l, --local-only  If in a virtualenv that has global access donot show
                        globally installed packages
      -w, --nowarn      Inhibit warnings about possibly confusing packages


Known Issues
------------

* To work with packages installed inside a virtualenv, pipdeptree also
  needs to be installed in the same virtualenv even if it's already
  installed globally.

* One thing you might have noticed already is that ``flask`` is shown
  as a dependency of ``flask-script``, which although correct, sounds
  a bit odd. ``flask-script`` is being used here *because* we are
  using ``flask`` and not the other way around. Same with
  ``sqlalchemy`` and ``alembic``.  I haven't yet thought about a
  possible solution to this!  (May be if libs that are "extensions"
  could be distinguished from the ones that are
  "dependencies". Suggestions are welcome.)


Runnings Tests (for contributors)
---------------------------------

Tests can be run against all version of python using `tox
<http://tox.readthedocs.org/en/latest/>`_ as follows:

.. code-block:: bash

    $ make test-tox

This assumes that you have python versions 2.6, 2.7, 3.2, 3.3 and 3.4
installed on your machine. (See more: tox.ini)

Or if you don't want to install all the versions of python but want to
run tests quickly against Python2.7 only:

.. code-block:: bash

    $ make test

Tests require some virtualenvs to be created, so another assumption is
that you have ``virtualenv`` installed.

Before pushing the code or sending pull requests it's recommended to
run ``make test-tox`` once so that tests are run on all environments.

(See more: Makefile)


License
-------

MIT (See LICENSE)