Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add json formatting option to pip show #7967

Closed
wants to merge 9 commits into from

Conversation

deveshks
Copy link
Contributor

@deveshks deveshks commented Apr 2, 2020

Fixes and closes #5261

Json printing logic is added, as well as supporting unit tests. Different outputs with json formats are show below for reference.

Help section of pip show

$ pip show --help

Usage:   
  pip show [options] <package> ...

Description:
  Show information about one or more installed packages.
  
  The output is in RFC-compliant mail header format.

Show Options:
  -f, --files                 Show the full list of installed files for each package.
  --format <list_format>      Select the output format among: header (default) or json

Output of pip show pip --format=header or pip show pip

$ pip show pip
Name: pip
Version: 20.1.dev0
Summary: The PyPA recommended tool for installing Python packages.
Home-page: https://pip.pypa.io/
Author: The pip developers
Author-email: pypa-dev@groups.google.com
License: MIT
Location: /Users/devesh/pip/src
Requires: 
Required-by: 

Output of pip show pip --format=json

[{
	"name": "pip",
	"version": "20.1.dev0",
	"summary": "The PyPA recommended tool for installing Python packages.",
	"home-page": "https://pip.pypa.io/",
	"author": "The pip developers",
	"author-email": "pypa-dev@groups.google.com",
	"license": "MIT",
	"location": "/Users/devesh/pip/src",
	"requires": [],
	"required-by": []
}]

Output of pip show pip -v --format=json

[{
	"name": "pip",
	"version": "20.1.dev0",
	"summary": "The PyPA recommended tool for installing Python packages.",
	"home-page": "https://pip.pypa.io/",
	"author": "The pip developers",
	"author-email": "pypa-dev@groups.google.com",
	"license": "MIT",
	"location": "/Users/devesh/pip/src",
	"requires": [],
	"required-by": [],
	"metadata-version": "1.2",
	"installer": "",
	"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Build Tools", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"],
	"entry-points": ["[console_scripts]", "pip = pip._internal.cli.main:main", "pip3 = pip._internal.cli.main:main", "pip3.8 = pip._internal.cli.main:main"]
}]

Output of pip show pip -f -v --format=json (When files can't be located)

[{
	"name": "pip",
	"version": "20.1.dev0",
	"summary": "The PyPA recommended tool for installing Python packages.",
	"home-page": "https://pip.pypa.io/",
	"author": "The pip developers",
	"author-email": "pypa-dev@groups.google.com",
	"license": "MIT",
	"location": "/Users/devesh/pip/src",
	"requires": [],
	"required-by": [],
	"metadata-version": "1.2",
	"installer": "",
	"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Build Tools", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"],
	"entry-points": ["[console_scripts]", "pip = pip._internal.cli.main:main", "pip3 = pip._internal.cli.main:main", "pip3.8 = pip._internal.cli.main:main"],
	"files": null
}]

Output of pip show tox -v -f --format=json (When files can be located)

[{
	"name": "tox",
	"version": "3.14.6",
	"summary": "tox is a generic virtualenv management and test command line tool",
	"home-page": "http://tox.readthedocs.org",
	"author": "Holger Krekel, Oliver Bestwalter, Bernát Gábor and others",
	"author-email": null,
	"license": "MIT",
	"location": "/Users/devesh/pip/.env/lib/python3.8/site-packages",
	"requires": ["pluggy", "packaging", "virtualenv", "filelock", "toml", "py", "six"],
	"required-by": [],
	"metadata-version": "2.1",
	"installer": "pip",
	"classifiers": ["Development Status :: 5 - Production/Stable", "Framework :: tox", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8"],
	"entry-points": ["[console_scripts]", "tox = tox:cmdline", "tox-quickstart = tox._quickstart:main"],
	"files": ["../../../bin/tox", "../../../bin/tox-quickstart", "tox-3.14.6.dist-info/INSTALLER", "tox-3.14.6.dist-info/LICENSE", "tox-3.14.6.dist-info/METADATA", "tox-3.14.6.dist-info/RECORD", "tox-3.14.6.dist-info/WHEEL", "tox-3.14.6.dist-info/entry_points.txt", "tox-3.14.6.dist-info/top_level.txt", "tox/__init__.py", "tox/__main__.py", "tox/__pycache__/__init__.cpython-38.pyc", "tox/__pycache__/__main__.cpython-38.pyc", "tox/__pycache__/_pytestplugin.cpython-38.pyc", "tox/__pycache__/_quickstart.cpython-38.pyc", "tox/__pycache__/action.cpython-38.pyc", "tox/__pycache__/cli.cpython-38.pyc", "tox/__pycache__/constants.cpython-38.pyc", "tox/__pycache__/exception.cpython-38.pyc", "tox/__pycache__/hookspecs.cpython-38.pyc", "tox/__pycache__/reporter.cpython-38.pyc", "tox/__pycache__/venv.cpython-38.pyc", "tox/__pycache__/version.cpython-38.pyc", "tox/_pytestplugin.py", "tox/_quickstart.py", "tox/action.py", "tox/cli.py", "tox/config/__init__.py", "tox/config/__pycache__/__init__.cpython-38.pyc", "tox/config/__pycache__/parallel.cpython-38.pyc", "tox/config/__pycache__/reporter.cpython-38.pyc", "tox/config/parallel.py", "tox/config/reporter.py", "tox/constants.py", "tox/exception.py", "tox/helper/__init__.py", "tox/helper/__pycache__/__init__.cpython-38.pyc", "tox/helper/__pycache__/build_isolated.cpython-38.pyc", "tox/helper/__pycache__/build_requires.cpython-38.pyc", "tox/helper/__pycache__/get_site_package_dir.cpython-38.pyc", "tox/helper/__pycache__/get_version.cpython-38.pyc", "tox/helper/build_isolated.py", "tox/helper/build_requires.py", "tox/helper/get_site_package_dir.py", "tox/helper/get_version.py", "tox/hookspecs.py", "tox/interpreters/__init__.py", "tox/interpreters/__pycache__/__init__.cpython-38.pyc", "tox/interpreters/__pycache__/common.cpython-38.pyc", "tox/interpreters/__pycache__/py_spec.cpython-38.pyc", "tox/interpreters/__pycache__/unix.cpython-38.pyc", "tox/interpreters/__pycache__/via_path.cpython-38.pyc", "tox/interpreters/common.py", "tox/interpreters/py_spec.py", "tox/interpreters/unix.py", "tox/interpreters/via_path.py", "tox/interpreters/windows/__init__.py", "tox/interpreters/windows/__pycache__/__init__.cpython-38.pyc", "tox/interpreters/windows/__pycache__/pep514.cpython-38.pyc", "tox/interpreters/windows/pep514.py", "tox/logs/__init__.py", "tox/logs/__pycache__/__init__.cpython-38.pyc", "tox/logs/__pycache__/command.cpython-38.pyc", "tox/logs/__pycache__/env.cpython-38.pyc", "tox/logs/__pycache__/result.cpython-38.pyc", "tox/logs/command.py", "tox/logs/env.py", "tox/logs/result.py", "tox/package/__init__.py", "tox/package/__pycache__/__init__.cpython-38.pyc", "tox/package/__pycache__/local.cpython-38.pyc", "tox/package/__pycache__/view.cpython-38.pyc", "tox/package/builder/__init__.py", "tox/package/builder/__pycache__/__init__.cpython-38.pyc", "tox/package/builder/__pycache__/isolated.cpython-38.pyc", "tox/package/builder/__pycache__/legacy.cpython-38.pyc", "tox/package/builder/isolated.py", "tox/package/builder/legacy.py", "tox/package/local.py", "tox/package/view.py", "tox/reporter.py", "tox/session/__init__.py", "tox/session/__pycache__/__init__.cpython-38.pyc", "tox/session/commands/__init__.py", "tox/session/commands/__pycache__/__init__.cpython-38.pyc", "tox/session/commands/__pycache__/help.cpython-38.pyc", "tox/session/commands/__pycache__/help_ini.cpython-38.pyc", "tox/session/commands/__pycache__/provision.cpython-38.pyc", "tox/session/commands/__pycache__/show_config.cpython-38.pyc", "tox/session/commands/__pycache__/show_env.cpython-38.pyc", "tox/session/commands/help.py", "tox/session/commands/help_ini.py", "tox/session/commands/provision.py", "tox/session/commands/run/__init__.py", "tox/session/commands/run/__pycache__/__init__.cpython-38.pyc", "tox/session/commands/run/__pycache__/parallel.cpython-38.pyc", "tox/session/commands/run/__pycache__/sequential.cpython-38.pyc", "tox/session/commands/run/parallel.py", "tox/session/commands/run/sequential.py", "tox/session/commands/show_config.py", "tox/session/commands/show_env.py", "tox/util/__init__.py", "tox/util/__pycache__/__init__.cpython-38.pyc", "tox/util/__pycache__/graph.cpython-38.pyc", "tox/util/__pycache__/lock.cpython-38.pyc", "tox/util/__pycache__/main.cpython-38.pyc", "tox/util/__pycache__/path.cpython-38.pyc", "tox/util/__pycache__/spinner.cpython-38.pyc", "tox/util/__pycache__/stdlib.cpython-38.pyc", "tox/util/graph.py", "tox/util/lock.py", "tox/util/main.py", "tox/util/path.py", "tox/util/spinner.py", "tox/util/stdlib.py", "tox/venv.py", "tox/version.py"]
}]

@deveshks deveshks mentioned this pull request Apr 2, 2020
@deveshks
Copy link
Contributor Author

deveshks commented Apr 3, 2020

Hi @chrahunt and @cjerdonek

Apologies for the ping but I saw your comments on the last PR attempting to implement show --json, and I have tried to implement this PR along those lines, with future PR's being added towards this effort as well.

I would appreciate it if you guys can shed any thoughts on this, and any necessary scope of improvement :)

Copy link
Member

@xavfernandez xavfernandez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we'd need an actual json printer and its tests :)

src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Now we'd need an actual json printer and its tests :)

Hi @xavfernandez

I was planning to implement the json printer and the associated tests in a follow up PR, so as to not crowd this one and making sure the default format tests are passing with the refactoring

@xavfernandez
Copy link
Member

I was planning to implement the json printer and the associated tests in a follow up PR, so as to not crowd this one and making sure the default format tests are passing with the refactoring

That's definitely a good idea but then I'd say you need to:

  • remove the news/5261.feature file in favor of a .trivial
  • remove the Fixes and Closes #5261 from the PR description
  • remove the print_results_json function (and the if option == ... checks in run.

@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

That's definitely a good idea but then I'd say you need to:

Hi @xavfernandez

Thanks for that, I have addressed all the points you made in the latest commits. Please have a look 😊

@xavfernandez xavfernandez added skip news Does not need a NEWS file entry (eg: trivial changes) type: refactor Refactoring code C: list/show 'pip list' or 'pip show' and removed skip news Does not need a NEWS file entry (eg: trivial changes) labels Apr 6, 2020
xavfernandez
xavfernandez previously approved these changes Apr 6, 2020
@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Thanks @xavfernandez for the approval. I will tag you to the follow up PR for this, which will add the
JSON printer, associated unit tests and command line options --format=

Hi @pradyunsg , Could I please get this PR merged as well :)

Copy link
Member

@xavfernandez xavfernandez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I did not check the code more thoroughly before reviewing but it seems that search_packages_info is already somewhat performing the role of the new get_package_info (i.e. collecting information before formatting): it might make for sense to modify the key/title (capitalize, etc) there ?

src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Sorry I did not check the code more thoroughly before reviewing but it seems that search_packages_info is already somewhat performing the role of the new get_package_info (i.e. collecting information before formatting): it might make for sense to modify the key/title (capitalize, etc) there ?

Hi @xavfernandez

If I understand correctly, search_packages_info is populating the different key-value pairs pertaining to a package, at different stages, and get_package_info is collecting that info and applying the necessary formatting in the end.

I would prefer to keep those two separate, as they were before this change (print_results was performing the formatting task) otherwise the complexity of search_packages_info will grow more.

What do you think?

@xavfernandez
Copy link
Member

Currently, we have search_packages_info collecting information and print_results that prints it.

We definitely want those 2 steps separated.

But currently in this PR, we now have search_packages_info collecting information, get_package_info applying light transformation (mainly changing key formats: classifiers -> Classifiers) and finally print_results_default that prints it: this seems needlessly complex.

I think get_package_info could be merged into either search_packages_info or print_results_default.

@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

I think get_package_info could be merged into either search_packages_info or print_results_default.

Hi @xavfernandez

I can also do it the way you mentioned where search_packages_info collects information and print_results_default that prints it in default format, and a print_results_json in a follow up PR to print it in the json format. Does that sounds better?

Actually I was thinking earlier that we have search_packages_info collecting information, get_package_info applying light transformation and print_results_default that prints it, but this light transformation will help us to print the json directly, as well as reduce the printing code by for loops.

But I am not sure which one is better, this or the idea above it?

@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Hi @xavfernandez

I have merged get_package_info and print_results_defaulttogether, and since the code has almost reverted to the older one, I will add print_results_json and the unit tests in this PR as well.

@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Hi @xavfernandez

I have added the JSON printer, and I have also copied over the unit tests to work with json formatting. Please take a look

@sbidoul
Copy link
Member

sbidoul commented Apr 6, 2020

Let's be careful not rushing this out. Once released it will be very hard to change.

We need to see if we can be compatible (or at least consistent) with pip list --format=json.

Perhaps it's a case where we'd want to document the output before implementing. Several fields are obvious (yet documenting their relation to standards would help clarify), some other less so.

@deveshks
Copy link
Contributor Author

deveshks commented Apr 6, 2020

Hi @sbidoul

Let's be careful not rushing this out. Once released it will be very hard to change.

Agreed.

We need to see if we can be compatible (or at least consistent) with pip list --format=json.

How can we be sure of that. Currently I have taken the default output and mapped it to json directly. The keys are the same along with the casing, and the values are either a string (this is for keys Name, Version, Summary, Home-page, Author, Author-email, License, Location, Metadata-Version and Installer , or a list of strings if it was a comma separated value. (this is for keys Requires, Required-by, Classifiers and Entry-points

The only exception is Files value is the string 'Cannot locate installed-files.txt' if we cannot find files, else it's a list of files.

Perhaps it's a case where we'd want to document the output before implementing. Several fields are obvious (yet documenting their relation to standards would help clarify), some other less so.

I do see that there is no documentation of what each field refers to in the pip show display in the latest documentation. Should I create a parallel PR modifying that and adding the information about what each value signifies from there before proceeding with this PR?

Once this document is agreed upon, I can just change around the keys and values for pip list according to that spec.

Copy link
Member

@xavfernandez xavfernandez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some documentation update would also be needed indeed 👍

src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
src/pip/_internal/commands/show.py Outdated Show resolved Hide resolved
src/pip/_internal/commands/show.py Show resolved Hide resolved
@deveshks
Copy link
Contributor Author

deveshks commented Apr 7, 2020

Some documentation update would also be needed indeed 👍

@xavfernandez I will create a separate companion PR to include the document changes and link it here.

Also do we want to update https://github.com/pypa/pip/blob/master/docs/html/reference/pip_show.rst for this ?

@BrownTruck
Copy link
Contributor

Hello!

I am an automated bot and I have noticed that this pull request is not currently able to be merged. If you are able to either merge the master branch into this pull request or rebase this pull request against master then it will be eligible for code review and hopefully merging!

@BrownTruck BrownTruck added the needs rebase or merge PR has conflicts with current master label May 18, 2020
@pypa-bot pypa-bot removed the needs rebase or merge PR has conflicts with current master label May 18, 2020
@deveshks
Copy link
Contributor Author

To move this PR ahead, I have added some suggestions made at #8008 (comment) into the document PR #8008

I am open to reviews of the document PR, and once that is in an acceptable state, I can start the implementation here according to what we have in the docs.

@BrownTruck
Copy link
Contributor

Hello!

I am an automated bot and I have noticed that this pull request is not currently able to be merged. If you are able to either merge the master branch into this pull request or rebase this pull request against master then it will be eligible for code review and hopefully merging!

@BrownTruck BrownTruck added the needs rebase or merge PR has conflicts with current master label May 24, 2020
@pypa-bot pypa-bot removed the needs rebase or merge PR has conflicts with current master label May 24, 2020
@deveshks
Copy link
Contributor Author

deveshks commented Jun 28, 2020

Hi @xavfernandez , @sbidoul

Since #8008 , the documentation PR is at a good stage now, pending discussion on the nitty-grittes of fields, I was wondering if I can start the implementation of the atleast the basic fields in print_results_json in order to move this PR forward?

@xavfernandez
Copy link
Member

@deveshks the safest would be to first make sure that most maintainers are on board with this change before implementing it :)

@deveshks
Copy link
Contributor Author

deveshks commented Jul 4, 2020

Thanks for the tip @xavfernandez . I will hold of on making changes here before getting agreement on what changes need to be made in the doc PR.

@BrownTruck
Copy link
Contributor

Hello!

I am an automated bot and I have noticed that this pull request is not currently able to be merged. If you are able to either merge the master branch into this pull request or rebase this pull request against master then it will be eligible for code review and hopefully merging!

@BrownTruck BrownTruck added the needs rebase or merge PR has conflicts with current master label Feb 4, 2021
@pypa-bot pypa-bot removed the needs rebase or merge PR has conflicts with current master label Feb 26, 2021
@github-actions github-actions bot added the needs rebase or merge PR has conflicts with current master label Aug 15, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C: list/show 'pip list' or 'pip show' needs rebase or merge PR has conflicts with current master state: needs eyes Needs a maintainer/triager to take a closer look type: refactor Refactoring code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pip show --json
6 participants