diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f7da40..072759d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: rev: v2.37.3 hooks: - id: pyupgrade - args: [ "--py37-plus" ] + args: ["--py37-plus"] - repo: https://github.com/PyCQA/isort rev: 5.10.1 hooks: @@ -24,30 +24,33 @@ repos: rev: 22.8.0 hooks: - id: black - args: [ --safe ] + args: [--safe] - repo: https://github.com/asottile/blacken-docs rev: v1.12.1 hooks: - id: blacken-docs - additional_dependencies: [ black==22.8 ] - - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 - hooks: - - id: rst-backticks + additional_dependencies: [black==22.8] - repo: https://github.com/tox-dev/tox-ini-fmt rev: "0.5.2" hooks: - id: tox-ini-fmt - args: [ "-p", "fix" ] + args: ["-p", "fix"] - repo: https://github.com/PyCQA/flake8 rev: 5.0.4 hooks: - id: flake8 additional_dependencies: - - flake8-bugbear==22.8.23 - - flake8-comprehensions==3.10 - - flake8-pytest-style==1.6 - - flake8-spellcheck==0.28 - - flake8-unused-arguments==0.0.11 - - flake8-noqa==1.2.9 - - pep8-naming==0.13.2 + - flake8-bugbear==22.8.23 + - flake8-comprehensions==3.10 + - flake8-pytest-style==1.6 + - flake8-spellcheck==0.28 + - flake8-unused-arguments==0.0.11 + - flake8-noqa==1.2.9 + - pep8-naming==0.13.2 + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v2.7.1" + hooks: + - id: prettier + additional_dependencies: + - "prettier@2.7.1" + - "@prettier/plugin-xml@2.2" diff --git a/.prettierrc.toml b/.prettierrc.toml new file mode 100644 index 0000000..ba170fe --- /dev/null +++ b/.prettierrc.toml @@ -0,0 +1,2 @@ +printWidth = 120 +proseWrap = "always" diff --git a/CHANGES.md b/CHANGES.md index 0eb2475..acf5bb8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,252 +1,174 @@ -Changelog -========= +# Changelog -2.2.1 ------ +## 2.2.1 -* Fix ``--user-only`` and ``--freeze`` flags which were broken after - the last release. +- Fix `--user-only` and `--freeze` flags which were broken after the last release. +- Fix for compatibility with new version of `graphviz` (\>= 0.18.1). -* Fix for compatibility with new version of ``graphviz`` (>= 0.18.1). +## 2.2.0 -2.2.0 ------ +- Fix pipdeptree to work with pip version 21.3. The \_internal pip api that was being used earlier is now replaced with + new functions. (PR #154) -* Fix pipdeptree to work with pip version 21.3. The _internal pip api - that was being used earlier is now replaced with new functions. (PR - #154) +## 2.1.0 -2.1.0 ------ +- JSON output is sorted alphabetically to make it deterministic +- Fix \--freeze option due to breaking changes in pip\'s internal api in version \> 21.1.1 +- Include license file in dist package -* JSON output is sorted alphabetically to make it deterministic +## 2.0.0 -* Fix --freeze option due to breaking changes in pip's internal api in - version > 21.1.1 +- Support for running in the context of a virtualenv (without installing pipdeptree inside the virtualenv) +- Avoid crash when rendering cyclic dependencies +- Fix graphviz (dot file) output +- Handle a (rare) case while guessing version of a package +- Migrate from travisCI to Github workflows +- Improve integration tests -* Include license file in dist package +## 2.0.0b1 (beta version) -2.0.0 ------ +- In this first beta release targeting [2.0.0]{.title-ref}, the underlying code is heavily refactored to make different + CLI options work well with each other. This was a serious limitation in older version [\<=1.0.0]{.title-ref} which + made it difficult to extend the tool. -* Support for running in the context of a virtualenv (without - installing pipdeptree inside the virtualenv) + For more information about the plans for 2.0.0 release, please check [docs/v2beta-opts.org]{.title-ref} file. -* Avoid crash when rendering cyclic dependencies + > - The [\--reverse]{.title-ref}, [\--packages]{.title-ref} and [\--exclude]{.title-ref} flags now work with + > [\--json-tree]{.title-ref} and [\--graph-output]{.title-ref} + > - Dropped support for python [3.3]{.title-ref} and added support for python [3.7]{.title-ref} and [3.8]{.title-ref} -* Fix graphviz (dot file) output +- Another problem with older version was that tests setup was convoluted and involved loading packages pickled from one + env into the current env (in which tests are run). Moreover there was no separation between unit tests and integration + tests (flaky) -* Handle a (rare) case while guessing version of a package + > - Tests have been separated into 2 suites (1) unit tests that totally rely on mock objects and run on every commit ( + > travis.ci) and (2) end-to-end tests that need to be run manually. + > - The test setup for end-to-end tests has been greatly simplified although the \"flakyness\"\" still remains because + > these tests are run against unpinned versions of [pip]{.title-ref}. However this is by design because we want to + > know when [pipdeptree]{.title-ref} fails with a new version of [pip]{.title-ref}. -* Migrate from travisCI to Github workflows +- Move continuous integration from Travis to Github Actions. -* Improve integration tests +## 1.0.0 -2.0.0b1 (beta version) ----------------------- +- Use [pkg_resources]{.title-ref} vendored with [pip]{.title-ref}. +- Besides this, there\'s no other change in this major version release. -* In this first beta release targeting `2.0.0`, the underlying code is - heavily refactored to make different CLI options work well with each - other. This was a serious limitation in older version `<=1.0.0` - which made it difficult to extend the tool. +## 0.13.2 - For more information about the plans for 2.0.0 release, please check - `docs/v2beta-opts.org` file. - - * The `--reverse`, `--packages` and `--exclude` flags now work - with `--json-tree` and `--graph-output` - * Dropped support for python `3.3` and added support for python - `3.7` and `3.8` - -* Another problem with older version was that tests setup was - convoluted and involved loading packages pickled from one env into - the current env (in which tests are run). Moreover there was no - separation between unit tests and integration tests (flaky) - - * Tests have been separated into 2 suites (1) unit tests that - totally rely on mock objects and run on every commit ( - travis.ci) and (2) end-to-end tests that need to be run - manually. - * The test setup for end-to-end tests has been greatly simplified - although the "flakyness"" still remains because these tests are - run against unpinned versions of `pip`. However this is by - design because we want to know when `pipdeptree` fails with a - new version of `pip`. - -* Move continuous integration from Travis to Github Actions. - -1.0.0 ------ - -* Use `pkg_resources` vendored with `pip`. - -* Besides this, there's no other change in this major version release. - - -0.13.2 ------- - -* Fixed call to `FrozenRequirement.to_dist` to handle changes to the - internal api of pip version 19.0. The api change is because - dependency links support has been removed in pip 19.0 +- Fixed call to [FrozenRequirement.to_dist]{.title-ref} to handle changes to the internal api of pip version 19.0. The + api change is because dependency links support has been removed in pip 19.0 See more: - - https://github.com/pypa/pip/pull/6060 - - https://github.com/pypa/pip/pull/5881/commits/46ffb13f13f69c509fd253329da49889008f8e23 + - + - -0.13.1 ------- +## 0.13.1 -* Fixed import after changes in pip._internal introduced in pip - version 18.1 +- Fixed import after changes in pip.\_internal introduced in pip version 18.1 -0.13.0 ------- +## 0.13.0 -* Added `--exclude` option to exclude packages specified as CSV +- Added [\--exclude]{.title-ref} option to exclude packages specified as CSV +- In case of multiple version specs eg. \=y, fix the order to ensure consistent output. The sorting is naive - puts + the \'\>\' prior to \'\<\', and \'!\'. +- \[Developer affecting\] Updated dependencies in test environments, thereby fixing the long standing issue of + inconsistent test behaviour. -* In case of multiple version specs eg. =y, fix the order to - ensure consistent output. The sorting is naive - puts the '>' prior - to '<', and '!'. +## 0.12.1 -* [Developer affecting] Updated dependencies in test environments, thereby - fixing the long standing issue of inconsistent test behaviour. +- Fix import of \'FrozenRequirement\' for pip 10.0.0 +## 0.12.0 -0.12.1 ------- +- Changes to make pipdeptree work with pip 10.0.0. This change is backward compatible. -* Fix import of 'FrozenRequirement' for pip 10.0.0 +## 0.11.0 +- Added support for nested json output ([\--json-tree]{.title-ref} flag). Behaviour of [\--json]{.title-ref} stays the + same. +- Test environments have been updated to fix the builds. -0.12.0 ------- +## 0.10.1 -* Changes to make pipdeptree work with pip 10.0.0. This change is - backward compatible. +- Fixed change of behaviour due to support for `--json` and `--packages` together. PR #65 was reverted for this. -0.11.0 ------- +## 0.10.0 -* Added support for nested json output (`--json-tree` flag). Behaviour - of `--json` stays the same. +- Dropped support for Python 2.6. +- `--json` and `--packages` options can now be used together. +- Fixed binary graphviz output on Python 3 -* Test environments have been updated to fix the builds. +## 0.9.0 -0.10.1 ------- +- Support for visualizing dependency tree of packages using Graphviz in various formats. +- Support to consider only packages installed in the user directory. +- Fix the output to use a better term, \"Any\" instead of \"None\" if a dependency doesn\'t need to be of a specific + version. +- CLI option to print version. -* Fixed change of behaviour due to support for ``--json`` and - ``--packages`` together. PR #65 was reverted for this. +## 0.8.0 -0.10.0 ------- +- Use pip\'s list of excluded default packages. This means that the `pipdeptree` package itself is no longer excluded + and will appear in the output tree. +- Fix the bug that caused a package to appear in conflicting deps although it\'s installed version could be guessed. -* Dropped support for Python 2.6. +## 0.7.0 -* ``--json`` and ``--packages`` options can now be used together. +- Fix for a bug in reverse mode. +- Alphabetical sorting of packages in the output. +- Fallback to guess installed version of packages \"skipped\" by pip. -* Fixed binary graphviz output on Python 3 +## 0.6.0 +- Better checking for possibly \"confusing\" dependencies, hence the word \"confusing\" in the warning message is now + replaced with \"coflicting\" \[PR#37\] +- Fix a bug when rendering dependencies of packages \[PR#38\] +- The `--nowarn` flag is now replaced with `--warn` with \'silence\', \'suppress\' and \'fail\' as possible values, thus + giving more control over what should happen when there are warnings. The default behaviour (ie. when the flag is not + specified) remains the same. \[PR#39\] +- Fixes for Python 3.5 support \[PR#40\] -0.9.0 ------ +## 0.5.0 -* Support for visualizing dependency tree of packages using Graphviz - in various formats. +- Add [\--reverse]{.title-ref} flag to show the dependency tree upside down. +- Add [\--packages]{.title-ref} flag to show only select packages in output. +- Add [\--json]{.title-ref} flag to output dependency tree as json that may be used by external tools. -* Support to consider only packages installed in the user directory. +## 0.4.3 -* Fix the output to use a better term, "Any" instead of "None" if a - dependency doesn't need to be of a specific version. +- Add python support classifiers to setup.py +- Include license and changelog in distribution tar ball +- Removed bullets from output of pipdeptree if the [freeze]{.title-ref} (-f) flag is set. +- Changes related to test setup and travis-ci integration. -* CLI option to print version. +## 0.4.2 +- Fix Python 3.x incompatibility ([next()]{.title-ref} instead of [.next()]{.title-ref}) +- Suppress error if a dep is in skipped packages -0.8.0 ------ +## 0.4.1 -* Use pip's list of excluded default packages. This means that the - ``pipdeptree`` package itself is no longer excluded and will appear - in the output tree. +- Fix: Show warning about cyclic deps only if found -* Fix the bug that caused a package to appear in conflicting deps - although it's installed version could be guessed. +## 0.4 +- Python 2.6 compatibility +- Fix infinite recursion in case of cyclic dependencies +- Show warnings about cyclic dependencies +- Travis integration and other improvements -0.7.0 ------ +## 0.3 -* Fix for a bug in reverse mode. -* Alphabetical sorting of packages in the output. -* Fallback to guess installed version of packages "skipped" by pip. +- Add [\--freeze]{.title-ref} flag +- Warn about possible confusing dependencies +- Some minor help text and README fixes -0.6.0 ------ +## 0.2 -* Better checking for possibly "confusing" dependencies, hence the - word "confusing" in the warning message is now replaced with - "coflicting" [PR#37] -* Fix a bug when rendering dependencies of packages [PR#38] -* The ``--nowarn`` flag is now replaced with ``--warn`` with - 'silence', 'suppress' and 'fail' as possible values, thus giving - more control over what should happen when there are warnings. The - default behaviour (ie. when the flag is not specified) remains the - same. [PR#39] -* Fixes for Python 3.5 support [PR#40] +- Minor fixes -0.5.0 ------ - -* Add `--reverse` flag to show the dependency tree upside down. -* Add `--packages` flag to show only select packages in output. -* Add `--json` flag to output dependency tree as json that may be used - by external tools. - - -0.4.3 ------ - -* Add python support classifiers to setup.py -* Include license and changelog in distribution tar ball -* Removed bullets from output of pipdeptree if the `freeze` (-f) flag - is set. -* Changes related to test setup and travis-ci integration. - - -0.4.2 ------ - -* Fix Python 3.x incompatibility (`next()` instead of `.next()`) -* Suppress error if a dep is in skipped packages - -0.4.1 ------ - -* Fix: Show warning about cyclic deps only if found - -0.4 ---- - -* Python 2.6 compatibility -* Fix infinite recursion in case of cyclic dependencies -* Show warnings about cyclic dependencies -* Travis integration and other improvements - -0.3 ---- - -* Add `--freeze` flag -* Warn about possible confusing dependencies -* Some minor help text and README fixes - -0.2 ---- - -* Minor fixes - -0.1 ---- +## 0.1 First version diff --git a/README.md b/README.md new file mode 100644 index 0000000..a848c8a --- /dev/null +++ b/README.md @@ -0,0 +1,302 @@ +# pipdeptree + +[![check](https://github.com/tox-dev/pipdeptree/actions/workflows/check.yml/badge.svg)](https://github.com/tox-dev/pipdeptree/actions/workflows/check.yml) + +`pipdeptree` is a command line utility for displaying the installed python packages in form of a dependency tree. It +works for packages installed globally on a machine as well as in a virtualenv. 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\'s also tedious to resolve conflicting dependencies that could have been installed because older version of `pip` +didn\'t have true dependency resolution[^1]. `pipdeptree` can help here by identifying conflicting dependencies +installed in the environment.R + +To some extent, `pipdeptree` is inspired by the `lein deps :tree` command of [Leiningen](http://leiningen.org/). + +## Installation + +```bash +pip install pipdeptree +``` + +pipdeptree has been tested with Python versions `2.7`, `3.5`, `3.6`, `3.7`, `3.8`, `3.9` as well as `pypy2` and `pypy3`. + +Python `2.6` is way past it\'s end of life but if you ever find yourself stuck on a legacy environment, version `0.9.0` +_might_ work. + +## Running in virtualenvs + +`New in ver. 2.0.0` + +If you want to run pipdeptree in the context of a particular virtualenv, you can specify the `--python` option. Note +that this capability has been recently added in version `2.0.0`. + +Alternately, you may also install pipdeptree inside the virtualenv and then run it from there. + +## Usage and examples + +To give you a brief idea, here is the output of `pipdeptree` compared with `pip freeze`: + +```bash +$ pip freeze +Flask==0.10.1 +itsdangerous==0.24 +Jinja2==2.11.2 +-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy +MarkupSafe==0.22 +pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl +Werkzeug==0.11.2 +``` + +And now see what `pipdeptree` outputs, + +```bash +$ pipdeptree +Warning!!! Possibly conflicting dependencies found: +* Jinja2==2.11.2 + - MarkupSafe [required: >=0.23, installed: 0.22] +------------------------------------------------------------------------ +Flask==0.10.1 + - itsdangerous [required: >=0.21, installed: 0.24] + - Jinja2 [required: >=2.4, installed: 2.11.2] + - MarkupSafe [required: >=0.23, installed: 0.22] + - Werkzeug [required: >=0.7, installed: 0.11.2] +Lookupy==0.1 +pipdeptree==2.0.0b1 + - pip [required: >=6.0.0, installed: 20.1.1] +setuptools==47.1.1 +wheel==0.34.2 +``` + +## Is it possible to find out why a particular package is installed? + +`New in ver. 0.5.0` + +Yes, there\'s a `--reverse` (or simply `-r`) flag for this. To find out which packages depend on a particular +package(s), it can be combined with `--packages` option as follows: + +```bash +$ pipdeptree --reverse --packages itsdangerous,MarkupSafe +Warning!!! Possibly conflicting dependencies found: +* Jinja2==2.11.2 + - MarkupSafe [required: >=0.23, installed: 0.22] +------------------------------------------------------------------------ +itsdangerous==0.24 + - Flask==0.10.1 [requires: itsdangerous>=0.21] +MarkupSafe==0.22 + - Jinja2==2.11.2 [requires: MarkupSafe>=0.23] + - Flask==0.10.1 [requires: Jinja2>=2.4] +``` + +## What\'s with the warning about conflicting dependencies? + +As seen in the above output, `pipdeptree` by default warns about possible conflicting dependencies. Any package that\'s +specified as a dependency of multiple packages with different versions is considered as a conflicting dependency. +Conflicting dependencies are possible if older version of pip\<=20.2 +([without the new resolver](https://github.com/pypa/pip/issues/988)[^2]) was ever used to install dependencies at some +point. The warning is printed to stderr instead of stdout and it can be completely silenced by specifying the +`-w silence` or `--warn silence` option. On the other hand, it can be made mode strict with `--warn fail`, in which case +the command will not only print the warnings to stderr but also exit with a non-zero status code. This is useful if you +want to fit this tool into your CI pipeline. + +**Note**: The `--warn` option is added in version `0.6.0`. If you are using an older version, use `--nowarn` flag to +silence the warnings. + +## Warnings about circular dependencies + +In case any of the packages have circular dependencies (eg. package A depends on package B and package B depends on +package A), then `pipdeptree` will print warnings about that as well. + +```bash +$ pipdeptree --exclude pip,pipdeptree,setuptools,wheel +Warning!!! Cyclic dependencies found: +- CircularDependencyA => CircularDependencyB => CircularDependencyA +- CircularDependencyB => CircularDependencyA => CircularDependencyB +------------------------------------------------------------------------ +wsgiref==0.1.2 +argparse==1.2.1 +``` + +Similar to the warnings about conflicting dependencies, these too are printed to stderr and can be controlled using the +`--warn` option. + +In the above example, you can also see `--exclude` option which is the opposite of `--packages` ie. these packages will +be excluded from the output. + +## Using pipdeptree to write requirements.txt file + +If you wish to track only top level packages in your `requirements.txt` file, it\'s possible by grep-ing[^3]. only the +top-level lines from the output, + +```bash +$ pipdeptree --warn silence | grep -E '^\w+' +Flask==0.10.1 +gnureadline==8.0.0 +Lookupy==0.1 +pipdeptree==2.0.0b1 +setuptools==47.1.1 +wheel==0.34.2 +``` + +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 its source is lost. To fix this, `pipdeptree` +must be run with a `-f` or `--freeze` flag. + +```bash +$ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+' +Flask==0.10.1 +gnureadline==8.0.0 +-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy +pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl +setuptools==47.1.1 +wheel==0.34.2 + +$ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+' > requirements.txt +``` + +The freeze flag will not prefix child dependencies with hyphens, so you could dump the entire output of `pipdeptree -f` +to the requirements.txt file thus making it human-friendly (due to indentations) as well as pip-friendly. + +```bash +$ pipdeptree -f | tee locked-requirements.txt +Flask==0.10.1 + itsdangerous==0.24 + Jinja2==2.11.2 + MarkupSafe==0.23 + Werkzeug==0.11.2 +gnureadline==8.0.0 +-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy +pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl + pip==20.1.1 +setuptools==47.1.1 +wheel==0.34.2 +``` + +On confirming that there are no conflicting dependencies, you can even treat this as a \"lock file\" where all packages, +including the transient dependencies will be pinned to their currently installed versions. Note that the +`locked-requirements.txt` file could end up with duplicate entries. Although `pip install` wouldn\'t complain about +that, you can avoid duplicate lines (at the cost of losing indentation) as follows, + +```bash +$ pipdeptree -f | sed 's/ //g' | sort -u > locked-requirements.txt +``` + +## Using pipdeptree with external tools + +`New in ver. 0.5.0` + +It\'s also possible to have `pipdeptree` output json representation of the dependency tree so that it may be used as +input to other external tools. + +```bash +$ pipdeptree --json +``` + +Note that `--json` will output a flat list of all packages with their immediate dependencies. This is not very useful in +itself. To obtain nested json, use `--json-tree` + +`New in ver. 0.11.0` + +```bash +$ pipdeptree --json-tree +``` + +## Visualizing the dependency graph + +![image](https://raw.githubusercontent.com/tox-dev/pipdeptree/main/docs/twine-pdt.png) + +The dependency graph can also be visualized using [GraphViz](http://www.graphviz.org/): + +```bash +$ pipdeptree --graph-output dot > dependencies.dot +$ pipdeptree --graph-output pdf > dependencies.pdf +$ pipdeptree --graph-output png > dependencies.png +$ pipdeptree --graph-output svg > dependencies.svg +``` + +Note that `graphviz` is an optional dependency ie. required only if you want to use `--graph-output`. If the version of +`graphviz` installed in the env is older than 0.18.1, then a warning will be displayed about upgrading `graphviz`. +Support for older versions of graphviz will be dropped soon. + +Since version `2.0.0b1`, `--package` and `--reverse` flags are supported for all output formats ie. text, json, +json-tree and graph. + +In earlier versions, `--json`, `--json-tree` and `--graph-output` options override `--package` and `--reverse`. + +## Usage + +```bash +usage: pipdeptree.py [-h] [-v] [-f] [--python PYTHON] [-a] [-l] [-u] + [-w [{silence,suppress,fail}]] [-r] [-p PACKAGES] + [-e PACKAGES] [-j] [--json-tree] + [--graph-output OUTPUT_FORMAT] + +Dependency tree of the installed python packages + +optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + -f, --freeze Print names so as to write freeze files + --python PYTHON Python to use to look for packages in it (default: + where installed) + -a, --all list all deps at top level + -l, --local-only If in a virtualenv that has global access do not show + globally installed packages + -u, --user-only Only show installations in the user site dir + -w [{silence,suppress,fail}], --warn [{silence,suppress,fail}] + Warning control. "suppress" will show warnings but + return 0 whether or not they are present. "silence" + will not show warnings at all and always return 0. + "fail" will show warnings and return 1 if any are + present. The default is "suppress". + -r, --reverse Shows the dependency tree in the reverse fashion ie. + the sub-dependencies are listed with the list of + packages that need them under them. + -p PACKAGES, --packages PACKAGES + Comma separated list of select packages to show in the + output. If set, --all will be ignored. + -e PACKAGES, --exclude PACKAGES + Comma separated list of select packages to exclude + from the output. If set, --all will be ignored. + -j, --json Display dependency tree as json. This will yield "raw" + output that may be used by external tools. This option + overrides all other options. + --json-tree Display dependency tree as json which is nested the + same way as the plain text output printed by default. + This option overrides all other options (except + --json). + --graph-output OUTPUT_FORMAT + Print a dependency graph in the specified output + format. Available are all formats supported by + GraphViz, e.g.: dot, jpeg, pdf, png, svg +``` + +## Known issues + +1. `pipdeptree` relies on the internal API of `pip`. I fully understand that it\'s a bad idea but it mostly works! On + rare occasions, it breaks when a new version of `pip` is out with backward incompatible changes in internal API. So + beware if you are using this tool in environments in which `pip` version is unpinned, specially automation or CD/CI + pipelines. + +## Limitations & Alternatives + +`pipdeptree` merely looks at the installed packages in the current environment using pip, constructs the tree, then +outputs it in the specified format. If you want to generate the dependency tree without installing the packages, then +you need a dependency resolver. You might want to check alternatives such as +[pipgrip](https://github.com/ddelange/pipgrip) or [poetry](https://github.com/python-poetry/poetry). + +## License + +MIT (See [LICENSE](./LICENSE)) + +## Footnotes + +[^1]: + pip version 20.3 has been released in Nov 2020 with the dependency resolver + \<\>\_ + +[^2]: + pip version 20.3 has been released in Nov 2020 with the dependency resolver + \<\>\_ + +[^3]: + If you are on windows (powershell) you can run `pipdeptree --warn silence | Select-String -Pattern '^\w+'` instead + of grep diff --git a/README.rst b/README.rst deleted file mode 100644 index acba021..0000000 --- a/README.rst +++ /dev/null @@ -1,442 +0,0 @@ -pipdeptree -========== - -.. image:: https://github.com/naiquevin/pipdeptree/workflows/check/badge.svg - :target: https://github.com/naiquevin/pipdeptree/actions - - -``pipdeptree`` is a command line utility for displaying the installed -python packages in form of a dependency tree. It works for packages -installed globally on a machine as well as in a virtualenv. 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's also tedious to resolve conflicting -dependencies that could have been installed because older version of -``pip`` didn't have true dependency resolution [1]_. ``pipdeptree`` -can help here by identifying conflicting dependencies installed in the -environment.R - -To some extent, ``pipdeptree`` is inspired by the ``lein deps :tree`` -command of `Leiningen `_. - - -Installation ------------- - -.. code-block:: bash - - $ pip install pipdeptree - -pipdeptree has been tested with Python versions ``2.7``, ``3.5``, -``3.6``, ``3.7``, ``3.8``, ``3.9`` as well as ``pypy2`` and ``pypy3``. - -Python ``2.6`` is way past it's end of life but if you ever find -yourself stuck on a legacy environment, version ``0.9.0`` *might* -work. - - -Running in virtualenvs ----------------------- - -``New in ver. 2.0.0`` - -If you want to run pipdeptree in the context of a particular -virtualenv, you can specify the ``--python`` option. Note that this -capability has been recently added in version ``2.0.0``. - -Alternately, you may also install pipdeptree inside the virtualenv and -then run it from there. - - -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 - itsdangerous==0.24 - Jinja2==2.11.2 - -e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy - MarkupSafe==0.22 - pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl - Werkzeug==0.11.2 - -And now see what ``pipdeptree`` outputs, - -.. code-block:: bash - - $ pipdeptree - Warning!!! Possibly conflicting dependencies found: - * Jinja2==2.11.2 - - MarkupSafe [required: >=0.23, installed: 0.22] - ------------------------------------------------------------------------ - Flask==0.10.1 - - itsdangerous [required: >=0.21, installed: 0.24] - - Jinja2 [required: >=2.4, installed: 2.11.2] - - MarkupSafe [required: >=0.23, installed: 0.22] - - Werkzeug [required: >=0.7, installed: 0.11.2] - Lookupy==0.1 - pipdeptree==2.0.0b1 - - pip [required: >=6.0.0, installed: 20.1.1] - setuptools==47.1.1 - wheel==0.34.2 - - -Is it possible to find out why a particular package is installed? ------------------------------------------------------------------ - -``New in ver. 0.5.0`` - -Yes, there's a ``--reverse`` (or simply ``-r``) flag for this. To find -out which packages depend on a particular package(s), it can be -combined with ``--packages`` option as follows: - -.. code-block:: bash - - $ pipdeptree --reverse --packages itsdangerous,MarkupSafe - Warning!!! Possibly conflicting dependencies found: - * Jinja2==2.11.2 - - MarkupSafe [required: >=0.23, installed: 0.22] - ------------------------------------------------------------------------ - itsdangerous==0.24 - - Flask==0.10.1 [requires: itsdangerous>=0.21] - MarkupSafe==0.22 - - Jinja2==2.11.2 [requires: MarkupSafe>=0.23] - - Flask==0.10.1 [requires: Jinja2>=2.4] - - -What's with the warning about conflicting dependencies? -------------------------------------------------------- - -As seen in the above output, ``pipdeptree`` by default warns about -possible conflicting dependencies. Any package that's specified as a -dependency of multiple packages with different versions is considered -as a conflicting dependency. Conflicting dependencies are possible if -older version of pip<=20.2 (`without the new resolver -`_ [1]_) was ever used to -install dependencies at some point. The warning is printed to stderr -instead of stdout and it can be completely silenced by specifying the -``-w silence`` or ``--warn silence`` option. On the other hand, it can -be made mode strict with ``--warn fail``, in which case the command -will not only print the warnings to stderr but also exit with a -non-zero status code. This is useful if you want to fit this tool into -your CI pipeline. - -**Note**: The ``--warn`` option is added in version ``0.6.0``. If you -are using an older version, use ``--nowarn`` flag to silence the -warnings. - - -Warnings about circular dependencies ------------------------------------- - -In case any of the packages have circular dependencies (eg. package A -depends on package B and package B depends on package A), then -``pipdeptree`` will print warnings about that as well. - -.. code-block:: bash - - $ pipdeptree --exclude pip,pipdeptree,setuptools,wheel - Warning!!! Cyclic dependencies found: - - CircularDependencyA => CircularDependencyB => CircularDependencyA - - CircularDependencyB => CircularDependencyA => CircularDependencyB - ------------------------------------------------------------------------ - wsgiref==0.1.2 - argparse==1.2.1 - -Similar to the warnings about conflicting dependencies, these too are -printed to stderr and can be controlled using the ``--warn`` option. - -In the above example, you can also see ``--exclude`` option which is -the opposite of ``--packages`` ie. these packages will be excluded -from the output. - - -Using pipdeptree to write requirements.txt file ------------------------------------------------ - -If you wish to track only top level packages in your -``requirements.txt`` file, it's possible by grep-ing [2]_. only the -top-level lines from the output, - -.. code-block:: bash - - $ pipdeptree --warn silence | grep -E '^\w+' - Flask==0.10.1 - gnureadline==8.0.0 - Lookupy==0.1 - pipdeptree==2.0.0b1 - setuptools==47.1.1 - wheel==0.34.2 - -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 its source -is lost. To fix this, ``pipdeptree`` must be run with a ``-f`` or -``--freeze`` flag. - -.. code-block:: bash - - $ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+' - Flask==0.10.1 - gnureadline==8.0.0 - -e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy - pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl - setuptools==47.1.1 - wheel==0.34.2 - - $ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+' > requirements.txt - -The freeze flag will not prefix child dependencies with hyphens, so -you could dump the entire output of ``pipdeptree -f`` to the -requirements.txt file thus making it human-friendly (due to -indentations) as well as pip-friendly. - -.. code-block:: bash - - $ pipdeptree -f | tee locked-requirements.txt - Flask==0.10.1 - itsdangerous==0.24 - Jinja2==2.11.2 - MarkupSafe==0.23 - Werkzeug==0.11.2 - gnureadline==8.0.0 - -e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy - pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl - pip==20.1.1 - setuptools==47.1.1 - wheel==0.34.2 - -On confirming that there are no conflicting dependencies, you can even -treat this as a "lock file" where all packages, including the -transient dependencies will be pinned to their currently installed -versions. Note that the ``locked-requirements.txt`` file could end up -with duplicate entries. Although ``pip install`` wouldn't complain -about that, you can avoid duplicate lines (at the cost of losing -indentation) as follows, - -.. code-block:: bash - - $ pipdeptree -f | sed 's/ //g' | sort -u > locked-requirements.txt - - -Using pipdeptree with external tools ------------------------------------- - -``New in ver. 0.5.0`` - -It's also possible to have ``pipdeptree`` output json representation -of the dependency tree so that it may be used as input to other -external tools. - -.. code-block:: bash - - $ pipdeptree --json - -Note that ``--json`` will output a flat list of all packages with -their immediate dependencies. This is not very useful in itself. To -obtain nested json, use ``--json-tree`` - -``New in ver. 0.11.0`` - -.. code-block:: bash - - $ pipdeptree --json-tree - - -Visualizing the dependency graph --------------------------------- - -.. image:: https://raw.githubusercontent.com/naiquevin/pipdeptree/master/docs/twine-pdt.png - -The dependency graph can also be visualized using `GraphViz -`_: - -.. code-block:: bash - - $ pipdeptree --graph-output dot > dependencies.dot - $ pipdeptree --graph-output pdf > dependencies.pdf - $ pipdeptree --graph-output png > dependencies.png - $ pipdeptree --graph-output svg > dependencies.svg - -Note that ``graphviz`` is an optional dependency ie. required only if -you want to use ``--graph-output``. If the version of ``graphviz`` -installed in the env is older than 0.18.1, then a warning will be -displayed about upgrading ``graphviz``. Support for older versions of -graphviz will be dropped soon. - -Since version ``2.0.0b1``, ``--package`` and ``--reverse`` flags are -supported for all output formats ie. text, json, json-tree and graph. - -In earlier versions, ``--json``, ``--json-tree`` and -``--graph-output`` options override ``--package`` and ``--reverse``. - - -Usage ------ - -.. code-block:: bash - - usage: pipdeptree.py [-h] [-v] [-f] [--python PYTHON] [-a] [-l] [-u] - [-w [{silence,suppress,fail}]] [-r] [-p PACKAGES] - [-e PACKAGES] [-j] [--json-tree] - [--graph-output OUTPUT_FORMAT] - - Dependency tree of the installed python packages - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -f, --freeze Print names so as to write freeze files - --python PYTHON Python to use to look for packages in it (default: - where installed) - -a, --all list all deps at top level - -l, --local-only If in a virtualenv that has global access do not show - globally installed packages - -u, --user-only Only show installations in the user site dir - -w [{silence,suppress,fail}], --warn [{silence,suppress,fail}] - Warning control. "suppress" will show warnings but - return 0 whether or not they are present. "silence" - will not show warnings at all and always return 0. - "fail" will show warnings and return 1 if any are - present. The default is "suppress". - -r, --reverse Shows the dependency tree in the reverse fashion ie. - the sub-dependencies are listed with the list of - packages that need them under them. - -p PACKAGES, --packages PACKAGES - Comma separated list of select packages to show in the - output. If set, --all will be ignored. - -e PACKAGES, --exclude PACKAGES - Comma separated list of select packages to exclude - from the output. If set, --all will be ignored. - -j, --json Display dependency tree as json. This will yield "raw" - output that may be used by external tools. This option - overrides all other options. - --json-tree Display dependency tree as json which is nested the - same way as the plain text output printed by default. - This option overrides all other options (except - --json). - --graph-output OUTPUT_FORMAT - Print a dependency graph in the specified output - format. Available are all formats supported by - GraphViz, e.g.: dot, jpeg, pdf, png, svg - -Known issues ------------- - -1. ``pipdeptree`` relies on the internal API of ``pip``. I fully - understand that it's a bad idea but it mostly works! On rare - occasions, it breaks when a new version of ``pip`` is out with - backward incompatible changes in internal API. So beware if you are - using this tool in environments in which ``pip`` version is - unpinned, specially automation or CD/CI pipelines. - - -Limitations & Alternatives --------------------------- - -``pipdeptree`` merely looks at the installed packages in the current -environment using pip, constructs the tree, then outputs it in the -specified format. If you want to generate the dependency tree without -installing the packages, then you need a dependency resolver. You -might want to check alternatives such as `pipgrip -`_ or `poetry -`_. - - -Runing Tests (for contributors) -------------------------------- - -There are 2 test suites in this repo: - -1. Unit tests that use mock objects. These are configured to run on - every push to the repo and on every PR thanks to Github Actions. - -2. End-to-end tests that are run against actual packages installed in - virtualenvs - -Unit tests can be run against all version of python using `tox -`_ as follows: - -.. code-block:: bash - - $ make test-tox-all - -This assumes that you have python versions specified in the -``tox.ini`` file. - -If you don't want to install all the versions of python but want to -run tests quickly against ``Python3.6`` only: - -.. code-block:: bash - - $ make test - -Unit tests are written using ``pytest`` and you can also run the tests -with code coverage as follows, - -.. code-block:: bash - - $ make test-cov - -On the other hand, end-to-end tests actually create virtualenvs, -install packages and then run tests against them. These tests are more -reliable in the sense that they also test ``pipdeptree`` with the -latest version of ``pip`` and ``setuptools``. - -The downside is that when new versions of ``pip`` or ``setuptools`` -are released, these need to be updated. At present the process is -manual but I have plans to setup nightly builds for these for faster -feedback. - -The end-to-end tests can be run as follows, - -.. code-block:: bash - - $ make test-e2e # starts with a clean virtualenvs - - $ # or - - $ make test-e2e-quick # reuses existing virtualenvs - -By default the e2e tests uses python executable ``python3.6``. To use -an alternate version set the environment var ``E2E_PYTHON_EXE``. - -.. code-block:: bash - - $ E2E_PYTHON_EXE=python2.7 make test-e2e - - -Release checklist ------------------ - -#. Make sure that tests pass on Github Actions. -#. Create a commit with following changes and push it to github -#. Update the ``__version__`` in the ``pipdeptree.py`` file. - - #. Add Changelog in ``CHANGES.md`` file. - #. Also update ``README.md`` if required. -#. Create an annotated tag on the above commit and push the tag to - github -#. Upload new version to PyPI. - - -License -------- - -MIT (See `LICENSE <./LICENSE>`_) - -Footnotes ---------- - -.. [1] pip version 20.3 has been released in Nov 2020 with the - dependency resolver - _ - -.. [2] If you are on windows (powershell) you can run - ``pipdeptree --warn silence | Select-String -Pattern '^\w+'`` - instead of grep diff --git a/docs/example-requirements.txt b/docs/example-requirements.txt deleted file mode 100644 index 7e15b1d..0000000 --- a/docs/example-requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -Flask==0.10.1 -itsdangerous==0.24 -Jinja2 -MarkupSafe==0.22 -Werkzeug==0.11.2 -argparse --e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy-master -gnureadline==8.0.0 diff --git a/pyproject.toml b/pyproject.toml index f064dc6..d3862a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,13 +5,13 @@ requires = ["hatchling>=1.8.1", "hatch-vcs>=0.2"] [project] name = "pipdeptree" description = 'Command line utility to show dependency tree of packages.' -readme = "README.rst" +readme = "README.md" license.file = "LICENSE" maintainers = [ { name = "Bernát Gábor", email = "gaborjbernat@gmail.com" }, { name = "Vineet Naik", email = "naikvin@gmail.com" }, ] -urls.Documentation = "https://github.com/tox-dev/pipdeptree/blob/main/README.rst#pipdeptree" +urls.Documentation = "https://github.com/tox-dev/pipdeptree/blob/main/README.md#pipdeptree" urls.Homepage = "https://github.com/tox-dev/pipdeptree" urls.Source = "https://github.com/tox-dev/pipdeptree" urls.Tracker = "https://github.com/tox-dev/pipdeptree/issues"