{"action":"created","issue":{"url":"https://api.github.com/repos/pypa/pip/issues/3654","repository_url":"https://api.github.com/repos/pypa/pip","labels_url":"https://api.github.com/repos/pypa/pip/issues/3654/labels{/name}","comments_url":"https://api.github.com/repos/pypa/pip/issues/3654/comments","events_url":"https://api.github.com/repos/pypa/pip/issues/3654/events","html_url":"https://github.com/pypa/pip/pull/3654","id":153112017,"number":3654,"title":"Column formatting for \"pip list\"","user":{"login":"dougthor42","id":5386897,"avatar_url":"https://avatars.githubusercontent.com/u/5386897?v=3","gravatar_id":"","url":"https://api.github.com/users/dougthor42","html_url":"https://github.com/dougthor42","followers_url":"https://api.github.com/users/dougthor42/followers","following_url":"https://api.github.com/users/dougthor42/following{/other_user}","gists_url":"https://api.github.com/users/dougthor42/gists{/gist_id}","starred_url":"https://api.github.com/users/dougthor42/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dougthor42/subscriptions","organizations_url":"https://api.github.com/users/dougthor42/orgs","repos_url":"https://api.github.com/users/dougthor42/repos","events_url":"https://api.github.com/users/dougthor42/events{/privacy}","received_events_url":"https://api.github.com/users/dougthor42/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2016-05-04T20:52:06Z","updated_at":"2016-05-07T14:50:35Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/pypa/pip/pulls/3654","html_url":"https://github.com/pypa/pip/pull/3654","diff_url":"https://github.com/pypa/pip/pull/3654.diff","patch_url":"https://github.com/pypa/pip/pull/3654.patch"},"body":"# Summary\r\nThis PR adds optional column formatting to `pip list` via the commands `--columns` and `--no-header`.\r\n\r\nFixes #3651.\r\n\r\n# Discussion\r\nThere is a lot of looping going on to accomplish this PR. I don't think it's a big deal because the list of installed packages is rarely large enough that having multiple loops would cause a significant slowdown. Where reasonable (for speed and readability), I've used list comprehensions instead.\r\n\r\nWhile the call signature of `output_package_listing` was changed, it was not changed in a way that would effect other calls since the new `options` argument defaults to `None`.\r\n\r\nIf `output_package_listing` is called with `options=None` then there is no change to the previous behavior.\r\n\r\n# Examples\r\nStandard output of `pip list` is not changed. New output looks like so:\r\n```\r\n$ pip list --columns\r\nPackage        Version\r\n-------------- ------------\r\ndocopt         0.6.2\r\nidlex          1.13\r\njedi           0.9.0\r\npip            8.1.1\r\nprompt-toolkit 0.60\r\nptpython       0.32\r\nPygments       2.1.3\r\npythonnet      2.1.0\r\nretry          0.8.1\r\nsetuptools     20.6.7\r\nsix            1.10.0\r\nsqlite-bro     0.8.11\r\nwcwidth        0.1.6\r\nwinpython      1.5.20160402\r\n\r\n$ pip list --columns --no-header\r\ndocopt         0.6.2\r\nidlex          1.13\r\njedi           0.9.0\r\npip            8.1.1\r\nprompt-toolkit 0.60\r\nptpython       0.32\r\nPygments       2.1.3\r\npythonnet      2.1.0\r\nretry          0.8.1\r\nsetuptools     20.6.7\r\nsix            1.10.0\r\nsqlite-bro     0.8.11\r\nwcwidth        0.1.6\r\nwinpython      1.5.20160402\r\n\r\n$ pip list --columns -o\r\nPackage    Version Latest Type\r\n---------- ------- ------ -----\r\nretry      0.8.1   0.9.1  wheel\r\nsetuptools 20.6.7  21.0.0 wheel\r\n\r\n$ pip list --columns\r\nPackage        Version      Location\r\n-------------- ------------ -----------------------------------\r\ncolorama       0.3.7\r\ndocopt         0.6.2\r\nidlex          1.13\r\njedi           0.9.0\r\npip            8.1.1\r\npluggy         0.3.1\r\nprompt-toolkit 0.60\r\nptpython       0.32\r\npy             1.4.31\r\nPygments       2.1.3\r\npytest         2.9.1\r\npythonnet      2.1.0\r\nsetuptools     20.6.7\r\nsix            1.10.0\r\nsqlite-bro     0.8.11\r\ntox            2.3.1\r\ntqdm           4.5.0        c:\\gitlab\\temp\\path with space\\tqdm\r\nvirtualenv     15.0.1\r\nwcwidth        0.1.6\r\nwinpython      1.5.20160402\r\n```\r\n\r\n<!-- Reviewable:start -->\r\n---\r\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"35\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/pypa/pip/3654)\r\n<!-- Reviewable:end -->\r\n"},"comment":{"url":"https://api.github.com/repos/pypa/pip/issues/comments/217642254","html_url":"https://github.com/pypa/pip/pull/3654#issuecomment-217642254","issue_url":"https://api.github.com/repos/pypa/pip/issues/3654","id":217642254,"user":{"login":"dstufft","id":145979,"avatar_url":"https://avatars.githubusercontent.com/u/145979?v=3","gravatar_id":"","url":"https://api.github.com/users/dstufft","html_url":"https://github.com/dstufft","followers_url":"https://api.github.com/users/dstufft/followers","following_url":"https://api.github.com/users/dstufft/following{/other_user}","gists_url":"https://api.github.com/users/dstufft/gists{/gist_id}","starred_url":"https://api.github.com/users/dstufft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dstufft/subscriptions","organizations_url":"https://api.github.com/users/dstufft/orgs","repos_url":"https://api.github.com/users/dstufft/repos","events_url":"https://api.github.com/users/dstufft/events{/privacy}","received_events_url":"https://api.github.com/users/dstufft/received_events","type":"User","site_admin":false},"created_at":"2016-05-07T14:50:35Z","updated_at":"2016-05-07T14:50:35Z","body":"I think you should be able to figure out the warning by just having three states on the same variable like this:\r\n\r\n```\r\n# TODO: When we switch the default, set default=True here and then\r\n#              adjust pip/commands/list.pip to remove ``and options.columns is None``.\r\ncolumns = partial(Option, \"--columns\", dest=\"columns\", action=\"store_true\")\r\nno_columns = partial(Option, \"--no-columns\", dest=\"columns\", action=\"store_false\")\r\n```\r\n\r\nI think this should work in such a way that if someone specifies ``--columns`` then the ``options.columns`` will be ``True``, if the specify ``--no-columns`` then it will be ``False``, and if the specify nothing it will be ``None``. Then your deprecation warning can be:\r\n\r\n```\r\n# TODO: Remove the ``and options.columns is None`` when we switch\r\n#              the default.\r\nif not options.columns and options.columns is None:\r\n    warnings.warn(...)"}}