From b87c55a03d78152357b0ab4cc330e960c16ccb26 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Fri, 3 Apr 2020 04:26:03 +0530 Subject: [PATCH 1/8] Add json formatting option to pip show --- news/5261.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/5261.feature diff --git a/news/5261.feature b/news/5261.feature new file mode 100644 index 00000000000..660e1c97cca --- /dev/null +++ b/news/5261.feature @@ -0,0 +1 @@ +Display information about packages in json format using pip show From c6cdb5173a1bee4e85951ec1231be75291ddfc7a Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 6 Apr 2020 14:04:16 +0530 Subject: [PATCH 2/8] Moved formatting decision to run() --- src/pip/_internal/commands/show.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index 3892c5959ee..b0a2bb74f15 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -49,10 +49,22 @@ def run(self, options, args): query = args results = search_packages_info(query) - if not print_results( - results, list_files=options.files, verbose=options.verbose): - return ERROR - return SUCCESS + pkg_infos_list = get_package_info(results, list_files=options.files, + verbose=options.verbose) + + # TODO Add option in command line + option = 'default' + return_status = False + + # Print the information from installed distributions found for a + # given option + if option == 'default': + return_status = print_results_default(pkg_infos_list) + + elif option == 'json': + return_status = print_results_json(pkg_infos_list) + + return SUCCESS if return_status else ERROR def search_packages_info(query): From 8a92ff1651c721532c6b57711fd303e4f5a75367 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 6 Apr 2020 14:19:47 +0530 Subject: [PATCH 3/8] Reverted json based changes --- src/pip/_internal/commands/show.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index b0a2bb74f15..c142f59b5df 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -49,20 +49,12 @@ def run(self, options, args): query = args results = search_packages_info(query) + + # Get list of package infos and print them pkg_infos_list = get_package_info(results, list_files=options.files, verbose=options.verbose) - # TODO Add option in command line - option = 'default' - return_status = False - - # Print the information from installed distributions found for a - # given option - if option == 'default': - return_status = print_results_default(pkg_infos_list) - - elif option == 'json': - return_status = print_results_json(pkg_infos_list) + return_status = print_results_default(pkg_infos_list) return SUCCESS if return_status else ERROR From a83517181749096618696986caf0b726c2aa6d64 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 6 Apr 2020 14:21:57 +0530 Subject: [PATCH 4/8] Replaced feature news entry with trivial --- news/5261.feature | 1 - news/FAC843E9-BB25-4CA9-9F01-0398E5B796ED.trivial | 0 2 files changed, 1 deletion(-) delete mode 100644 news/5261.feature create mode 100644 news/FAC843E9-BB25-4CA9-9F01-0398E5B796ED.trivial diff --git a/news/5261.feature b/news/5261.feature deleted file mode 100644 index 660e1c97cca..00000000000 --- a/news/5261.feature +++ /dev/null @@ -1 +0,0 @@ -Display information about packages in json format using pip show diff --git a/news/FAC843E9-BB25-4CA9-9F01-0398E5B796ED.trivial b/news/FAC843E9-BB25-4CA9-9F01-0398E5B796ED.trivial new file mode 100644 index 00000000000..e69de29bb2d From 8e729c6f5af7a485c622992799eac533de9fe048 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 6 Apr 2020 18:38:26 +0530 Subject: [PATCH 5/8] Merging get_package_info to print_results_default --- src/pip/_internal/commands/show.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index c142f59b5df..ee62bbd687b 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -48,13 +48,11 @@ def run(self, options, args): return ERROR query = args - results = search_packages_info(query) - # Get list of package infos and print them - pkg_infos_list = get_package_info(results, list_files=options.files, - verbose=options.verbose) - - return_status = print_results_default(pkg_infos_list) + results = search_packages_info(query) + return_status = print_results_default(results, + list_files=options.files, + verbose=options.verbose) return SUCCESS if return_status else ERROR @@ -149,10 +147,9 @@ def get_requiring_packages(package_name): yield package -def print_results(distributions, list_files=False, verbose=False): - # type: (Iterator[Dict[str, str]], bool, bool) -> bool +def print_results_default(distributions, list_files=False, verbose=False): """ - Print the information from installed distributions found. + Print the information from installed distributions found in default format. """ results_printed = False for i, dist in enumerate(distributions): From 8def1b0080d4b3f51d5d8ca2c7c4ebb04259eef9 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Mon, 6 Apr 2020 21:02:19 +0530 Subject: [PATCH 6/8] Changes to add json printer and associated unit tests --- src/pip/_internal/commands/show.py | 76 +++++++++++++- tests/functional/test_show.py | 158 ++++++++++++++++++++++++++++- 2 files changed, 229 insertions(+), 5 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index ee62bbd687b..7e0633ca697 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +import json import logging import os from email.parser import FeedParser @@ -38,7 +39,14 @@ def add_options(self): action='store_true', default=False, help='Show the full list of installed files for each package.') - + self.cmd_opts.add_option( + '--format', + action='store', + dest='list_format', + default="header", + choices=('header', 'json'), + help="Select the output format among: header (default) or json", + ) self.parser.insert_option_group(0, self.cmd_opts) def run(self, options, args): @@ -46,13 +54,24 @@ def run(self, options, args): if not args: logger.warning('ERROR: Please provide a package name or names.') return ERROR + query = args # Get list of package infos and print them results = search_packages_info(query) - return_status = print_results_default(results, - list_files=options.files, - verbose=options.verbose) + return_status = False + + if options.list_format == 'header': + + return_status = print_results_default(results, + list_files=options.files, + verbose=options.verbose) + + elif options.list_format == 'json': + + return_status = print_results_json(results, + list_files=options.files, + verbose=options.verbose) return SUCCESS if return_status else ERROR @@ -185,3 +204,52 @@ def print_results_default(distributions, list_files=False, verbose=False): if "files" not in dist: write_output("Cannot locate installed-files.txt") return results_printed + + +def print_results_json(distributions, list_files=False, verbose=False): + """ + Build a dictionary with information from installed distributions found. + """ + + results_printed = False + pkg_infos_list = [] + + for i, dist in enumerate(distributions): + results_printed = True + pkg_info = {} + + pkg_info["Name"] = dist.get('name', '') + pkg_info["Version"] = dist.get('version', '') + pkg_info["Summary"] = dist.get('summary', '') + pkg_info["Home-page"] = dist.get('home-page', '') + pkg_info["Author"] = dist.get('author', '') + pkg_info["Author-email"] = dist.get('author-email', '') + pkg_info["License"] = dist.get('license', '') + pkg_info["Location"] = dist.get('location', '') + pkg_info["Requires"] = dist.get('requires', []) + pkg_info["Required-by"] = dist.get('required_by', []) + + if verbose: + pkg_info["Metadata-Version"] = dist.get('metadata-version', '') + pkg_info["Installer"] = dist.get('installer', '') + + pkg_info["Classifiers"] = [] + for classifier in dist.get('classifiers', []): + pkg_info["Classifiers"].append(classifier) + + pkg_info["Entry-points"] = [] + for entry in dist.get('entry_points', []): + pkg_info["Entry-points"].append(entry.strip()) + + if list_files: + if "files" not in dist: + pkg_info["Files"] = 'Cannot locate installed-files.txt' + else: + pkg_info["Files"] = [] + for line in dist.get('files', []): + pkg_info["Files"].append(line.strip()) + + pkg_infos_list.append(pkg_info) + + write_output(json.dumps(pkg_infos_list, ensure_ascii=False)) + return results_printed diff --git a/tests/functional/test_show.py b/tests/functional/test_show.py index c19228b566c..21a5109c1b8 100644 --- a/tests/functional/test_show.py +++ b/tests/functional/test_show.py @@ -1,3 +1,4 @@ +import json import os import re @@ -21,6 +22,19 @@ def test_basic_show(script): assert 'Requires: ' in lines +def test_basic_show_json(script): + """ + Test end to end test for show command. + """ + result = script.pip('show', 'pip', '--format=json') + data = json.loads(result.stdout)[0] + assert len(data) == 10 + assert data['Name'] == 'pip' + assert data['Version'] == '{}'.format(__version__) + assert 'Location' in data + assert 'Requires' in data + + def test_show_with_files_not_found(script, data): """ Test for show command with installed files listing enabled and @@ -39,6 +53,23 @@ def test_show_with_files_not_found(script, data): assert 'Cannot locate installed-files.txt' in lines +def test_show_with_files_not_found_json(script, data): + """ + Test for show command with installed files listing enabled and + installed-files.txt not found. + """ + editable = data.packages.joinpath('SetupPyUTF8') + script.pip('install', '-e', editable) + result = script.pip('show', '-f', 'SetupPyUTF8', '--format=json') + data = json.loads(result.stdout)[0] + assert data['Name'] == 'SetupPyUTF8' + assert data['Version'] == '0.0.0' + assert 'Location' in data + assert 'Requires' in data + assert 'Files' in data + assert data['Files'] == "Cannot locate installed-files.txt" + + def test_show_with_files_from_wheel(script, data): """ Test that a wheel's files can be listed @@ -52,6 +83,18 @@ def test_show_with_files_from_wheel(script, data): assert re.search(r"Files:\n( .+\n)+", result.stdout) +def test_show_with_files_from_wheel_json(script, data): + """ + Test that a wheel's files can be listed + """ + wheel_file = data.packages.joinpath('simple.dist-0.1-py2.py3-none-any.whl') + script.pip('install', '--no-index', wheel_file) + result = script.pip('show', '-f', 'simple.dist', '--format=json') + data = json.loads(result.stdout)[0] + assert data['Name'] == 'simple.dist' + assert data['Files'] + + @pytest.mark.network def test_show_with_all_files(script): """ @@ -64,6 +107,17 @@ def test_show_with_all_files(script): assert re.search(r"Files:\n( .+\n)+", result.stdout) +@pytest.mark.network +def test_show_with_all_files_json(script): + """ + Test listing all files in the show command. + """ + script.pip('install', 'initools==0.2') + result = script.pip('show', '--files', 'initools', '--format=json') + data = json.loads(result.stdout)[0] + assert data['Files'] + + def test_missing_argument(script): """ Test show command with no arguments. @@ -108,6 +162,21 @@ def test_report_mixed_not_found(script): assert 'Name: pip' in lines +def test_report_mixed_not_found_json(script): + """ + Test passing a mixture of found and not-found names. + """ + # We test passing non-canonicalized names. + result = script.pip( + 'show', 'Abcd3', 'A-B-C', 'pip', '--format=json', + allow_stderr_warning=True + ) + assert 'WARNING: Package(s) not found: A-B-C, Abcd3' in result.stderr + print(result.stdout) + data = json.loads(result.stdout)[0] + assert data['Name'] == 'pip' + + def test_search_any_case(): """ Search for a package in any case. @@ -138,6 +207,17 @@ def test_show_verbose_with_classifiers(script): assert "Intended Audience :: Developers" in result.stdout +def test_show_verbose_with_classifiers_json(script): + """ + Test that classifiers can be listed + """ + result = script.pip('show', 'pip', '--verbose', '--format=json') + data = json.loads(result.stdout)[0] + assert data['Name'] == 'pip' + assert data['Classifiers'] + assert "Intended Audience :: Developers" in data["Classifiers"] + + def test_show_verbose_installer(script, data): """ Test that the installer is shown (this currently needs a wheel install) @@ -150,6 +230,18 @@ def test_show_verbose_installer(script, data): assert 'Installer: pip' in lines +def test_show_verbose_installer_json(script, data): + """ + Test that the installer is shown (this currently needs a wheel install) + """ + wheel_file = data.packages.joinpath('simple.dist-0.1-py2.py3-none-any.whl') + script.pip('install', '--no-index', wheel_file) + result = script.pip('show', '--verbose', 'simple.dist', '--format=json') + data = json.loads(result.stdout)[0] + assert data['Name'] == 'simple.dist' + assert data['Installer'] == 'pip' + + def test_show_verbose(script): """ Test end to end test for verbose show command. @@ -162,6 +254,17 @@ def test_show_verbose(script): assert 'Classifiers:' in lines +def test_show_verbose_json(script): + """ + Test end to end test for verbose show command. + """ + result = script.pip('show', '--verbose', 'pip', '--format=json') + data = json.loads(result.stdout)[0] + + assert {'Metadata-Version', 'Installer', + 'Entry-points', 'Classifiers'} <= set(data) + + def test_all_fields(script): """ Test that all the fields are present @@ -175,6 +278,18 @@ def test_all_fields(script): assert actual == expected +def test_all_fields_json(script): + """ + Test that all the fields are present + """ + result = script.pip('show', 'pip', '--format=json') + data = json.loads(result.stdout)[0] + expected = {'Name', 'Version', 'Summary', 'Home-page', 'Author', + 'Author-email', 'License', 'Location', 'Requires', + 'Required-by'} + assert set(data) == expected + + def test_pip_show_is_short(script): """ Test that pip show stays short @@ -184,6 +299,15 @@ def test_pip_show_is_short(script): assert len(lines) <= 10 +def test_pip_show_is_short_json(script): + """ + Test that pip show stays short + """ + result = script.pip('show', 'pip', '--format=json') + data = json.loads(result.stdout)[0] + assert len(data) <= 10 + + def test_pip_show_divider(script, data): """ Expect a divider between packages @@ -222,6 +346,22 @@ def test_show_required_by_packages_basic(script, data): assert 'Required-by: requires-simple' in lines +def test_show_required_by_packages_basic_json(script, data): + """ + Test that installed packages that depend on this package are shown + """ + editable_path = os.path.join(data.src, 'requires_simple') + script.pip( + 'install', '--no-index', '-f', data.find_links, editable_path + ) + + result = script.pip('show', 'simple', '--format=json') + data = json.loads(result.stdout)[0] + + assert data['Name'] == 'simple' + assert data['Required-by'] == ['requires-simple'] + + def test_show_required_by_packages_capitalized(script, data): """ Test that the installed packages which depend on a package are shown @@ -239,6 +379,23 @@ def test_show_required_by_packages_capitalized(script, data): assert 'Required-by: Requires-Capitalized' in lines +def test_show_required_by_packages_capitalized_json(script, data): + """ + Test that the installed packages which depend on a package are shown + where the package has a capital letter + """ + editable_path = os.path.join(data.src, 'requires_capitalized') + script.pip( + 'install', '--no-index', '-f', data.find_links, editable_path + ) + + result = script.pip('show', 'simple', '--format=json') + data = json.loads(result.stdout)[0] + + assert data['Name'] == 'simple' + assert data['Required-by'] == ['Requires-Capitalized'] + + def test_show_required_by_packages_requiring_capitalized(script, data): """ Test that the installed packages which depend on a package are shown @@ -256,7 +413,6 @@ def test_show_required_by_packages_requiring_capitalized(script, data): result = script.pip('show', 'Requires_Capitalized') lines = result.stdout.splitlines() - print(lines) assert 'Name: Requires-Capitalized' in lines assert 'Required-by: requires-requires-capitalized' in lines From 58acd6b6411e0aff73002bbe806f7eaaa8543efd Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Thu, 9 Apr 2020 10:37:26 +0530 Subject: [PATCH 7/8] Lowercasing keys in json format --- src/pip/_internal/commands/show.py | 49 +++++++++++++------------- tests/functional/test_show.py | 55 ++++++++++++++---------------- 2 files changed, 50 insertions(+), 54 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index 7e0633ca697..a4f9f87f9d3 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -208,48 +208,47 @@ def print_results_default(distributions, list_files=False, verbose=False): def print_results_json(distributions, list_files=False, verbose=False): """ - Build a dictionary with information from installed distributions found. + Build a dictionary with information from installed distributions + found in JSON format. """ results_printed = False pkg_infos_list = [] - for i, dist in enumerate(distributions): + for dist in distributions: results_printed = True pkg_info = {} - pkg_info["Name"] = dist.get('name', '') - pkg_info["Version"] = dist.get('version', '') - pkg_info["Summary"] = dist.get('summary', '') - pkg_info["Home-page"] = dist.get('home-page', '') - pkg_info["Author"] = dist.get('author', '') - pkg_info["Author-email"] = dist.get('author-email', '') - pkg_info["License"] = dist.get('license', '') - pkg_info["Location"] = dist.get('location', '') - pkg_info["Requires"] = dist.get('requires', []) - pkg_info["Required-by"] = dist.get('required_by', []) + pkg_info["name"] = dist.get('name', '') + pkg_info["version"] = dist.get('version', '') - if verbose: - pkg_info["Metadata-Version"] = dist.get('metadata-version', '') - pkg_info["Installer"] = dist.get('installer', '') + pkg_info["summary"] = dist.get('summary', '') + pkg_info["home-page"] = dist.get('home-page', '') + pkg_info["author"] = dist.get('author', '') + pkg_info["author-email"] = dist.get('author-email', '') + pkg_info["license"] = dist.get('license', '') + pkg_info["location"] = dist.get('location', '') + pkg_info["requires"] = dist.get('requires', []) + pkg_info["required-by"] = dist.get('required_by', []) - pkg_info["Classifiers"] = [] - for classifier in dist.get('classifiers', []): - pkg_info["Classifiers"].append(classifier) + if verbose: - pkg_info["Entry-points"] = [] - for entry in dist.get('entry_points', []): - pkg_info["Entry-points"].append(entry.strip()) + pkg_info["metadata-version"] = dist.get('metadata-version', '') + pkg_info["installer"] = dist.get('installer', '') + pkg_info["classifiers"] = dist.get('classifiers', []) + pkg_info["entry-points"] = \ + [entry.strip() for entry in dist.get('entry_points')]\ + if 'entry_points' in dist else [] if list_files: if "files" not in dist: - pkg_info["Files"] = 'Cannot locate installed-files.txt' + pkg_info["files"] = None else: - pkg_info["Files"] = [] - for line in dist.get('files', []): - pkg_info["Files"].append(line.strip()) + pkg_info['files'] = [line.strip() + for line in dist.get('files')] pkg_infos_list.append(pkg_info) write_output(json.dumps(pkg_infos_list, ensure_ascii=False)) + return results_printed diff --git a/tests/functional/test_show.py b/tests/functional/test_show.py index 21a5109c1b8..056025133aa 100644 --- a/tests/functional/test_show.py +++ b/tests/functional/test_show.py @@ -29,10 +29,9 @@ def test_basic_show_json(script): result = script.pip('show', 'pip', '--format=json') data = json.loads(result.stdout)[0] assert len(data) == 10 - assert data['Name'] == 'pip' - assert data['Version'] == '{}'.format(__version__) - assert 'Location' in data - assert 'Requires' in data + assert data['name'] == 'pip' + assert data['version'] == '{}'.format(__version__) + assert {'location', 'requires'} <= set(data) def test_show_with_files_not_found(script, data): @@ -62,12 +61,10 @@ def test_show_with_files_not_found_json(script, data): script.pip('install', '-e', editable) result = script.pip('show', '-f', 'SetupPyUTF8', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'SetupPyUTF8' - assert data['Version'] == '0.0.0' - assert 'Location' in data - assert 'Requires' in data - assert 'Files' in data - assert data['Files'] == "Cannot locate installed-files.txt" + assert data['name'] == 'SetupPyUTF8' + assert data['version'] == '0.0.0' + assert {'location', 'requires'} <= set(data) + assert not data['files'] def test_show_with_files_from_wheel(script, data): @@ -91,8 +88,8 @@ def test_show_with_files_from_wheel_json(script, data): script.pip('install', '--no-index', wheel_file) result = script.pip('show', '-f', 'simple.dist', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'simple.dist' - assert data['Files'] + assert data['name'] == 'simple.dist' + assert data['files'] @pytest.mark.network @@ -115,7 +112,7 @@ def test_show_with_all_files_json(script): script.pip('install', 'initools==0.2') result = script.pip('show', '--files', 'initools', '--format=json') data = json.loads(result.stdout)[0] - assert data['Files'] + assert data['files'] def test_missing_argument(script): @@ -174,7 +171,7 @@ def test_report_mixed_not_found_json(script): assert 'WARNING: Package(s) not found: A-B-C, Abcd3' in result.stderr print(result.stdout) data = json.loads(result.stdout)[0] - assert data['Name'] == 'pip' + assert data['name'] == 'pip' def test_search_any_case(): @@ -213,9 +210,9 @@ def test_show_verbose_with_classifiers_json(script): """ result = script.pip('show', 'pip', '--verbose', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'pip' - assert data['Classifiers'] - assert "Intended Audience :: Developers" in data["Classifiers"] + assert data['name'] == 'pip' + assert data['classifiers'] + assert "Intended Audience :: Developers" in data["classifiers"] def test_show_verbose_installer(script, data): @@ -238,8 +235,8 @@ def test_show_verbose_installer_json(script, data): script.pip('install', '--no-index', wheel_file) result = script.pip('show', '--verbose', 'simple.dist', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'simple.dist' - assert data['Installer'] == 'pip' + assert data['name'] == 'simple.dist' + assert data['installer'] == 'pip' def test_show_verbose(script): @@ -261,8 +258,8 @@ def test_show_verbose_json(script): result = script.pip('show', '--verbose', 'pip', '--format=json') data = json.loads(result.stdout)[0] - assert {'Metadata-Version', 'Installer', - 'Entry-points', 'Classifiers'} <= set(data) + assert {'metadata-version', 'installer', + 'entry-points', 'classifiers'} <= set(data) def test_all_fields(script): @@ -284,9 +281,9 @@ def test_all_fields_json(script): """ result = script.pip('show', 'pip', '--format=json') data = json.loads(result.stdout)[0] - expected = {'Name', 'Version', 'Summary', 'Home-page', 'Author', - 'Author-email', 'License', 'Location', 'Requires', - 'Required-by'} + expected = {'name', 'version', 'summary', 'home-page', 'author', + 'author-email', 'license', 'location', 'requires', + 'required-by'} assert set(data) == expected @@ -358,8 +355,8 @@ def test_show_required_by_packages_basic_json(script, data): result = script.pip('show', 'simple', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'simple' - assert data['Required-by'] == ['requires-simple'] + assert data['name'] == 'simple' + assert data['required-by'] == ['requires-simple'] def test_show_required_by_packages_capitalized(script, data): @@ -392,8 +389,8 @@ def test_show_required_by_packages_capitalized_json(script, data): result = script.pip('show', 'simple', '--format=json') data = json.loads(result.stdout)[0] - assert data['Name'] == 'simple' - assert data['Required-by'] == ['Requires-Capitalized'] + assert data['name'] == 'simple' + assert data['required-by'] == ['Requires-Capitalized'] def test_show_required_by_packages_requiring_capitalized(script, data): @@ -448,9 +445,9 @@ def test_show_include_work_dir_pkg(script): expect_stderr=True, cwd=pkg_path) script.environ.update({'PYTHONPATH': pkg_path}) - # Show should include package simple when run from package directory, # when package directory is in PYTHONPATH result = script.pip('show', 'simple', cwd=pkg_path) lines = result.stdout.splitlines() assert 'Name: simple' in lines + From 7f9551b674803f7b9505282a2468949522a49a47 Mon Sep 17 00:00:00 2001 From: Devesh Kumar Singh Date: Sun, 28 Jun 2020 17:12:32 +0530 Subject: [PATCH 8/8] Fixed type annotations --- src/pip/_internal/commands/show.py | 8 +++++--- tests/functional/test_show.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index a4f9f87f9d3..6e402036c05 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -15,7 +15,7 @@ if MYPY_CHECK_RUNNING: from optparse import Values - from typing import List, Dict, Iterator + from typing import List, Dict, Iterator, Any logger = logging.getLogger(__name__) @@ -167,6 +167,7 @@ def get_requiring_packages(package_name): def print_results_default(distributions, list_files=False, verbose=False): + # type: (Iterator[Dict[str, str]], bool, bool) -> bool """ Print the information from installed distributions found in default format. """ @@ -207,6 +208,7 @@ def print_results_default(distributions, list_files=False, verbose=False): def print_results_json(distributions, list_files=False, verbose=False): + # type: (Iterator[Dict[str, Any]], bool, bool) -> bool """ Build a dictionary with information from installed distributions found in JSON format. @@ -237,7 +239,7 @@ def print_results_json(distributions, list_files=False, verbose=False): pkg_info["installer"] = dist.get('installer', '') pkg_info["classifiers"] = dist.get('classifiers', []) pkg_info["entry-points"] = \ - [entry.strip() for entry in dist.get('entry_points')]\ + [entry.strip() for entry in dist.get('entry_points', [])]\ if 'entry_points' in dist else [] if list_files: @@ -245,7 +247,7 @@ def print_results_json(distributions, list_files=False, verbose=False): pkg_info["files"] = None else: pkg_info['files'] = [line.strip() - for line in dist.get('files')] + for line in dist.get('files', [])] pkg_infos_list.append(pkg_info) diff --git a/tests/functional/test_show.py b/tests/functional/test_show.py index 056025133aa..bec7ff1695c 100644 --- a/tests/functional/test_show.py +++ b/tests/functional/test_show.py @@ -410,6 +410,7 @@ def test_show_required_by_packages_requiring_capitalized(script, data): result = script.pip('show', 'Requires_Capitalized') lines = result.stdout.splitlines() + print(lines) assert 'Name: Requires-Capitalized' in lines assert 'Required-by: requires-requires-capitalized' in lines @@ -450,4 +451,3 @@ def test_show_include_work_dir_pkg(script): result = script.pip('show', 'simple', cwd=pkg_path) lines = result.stdout.splitlines() assert 'Name: simple' in lines -