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

Console: Add "--top-level" flag to show command. #7415

Merged
merged 11 commits into from
Apr 19, 2023
1 change: 1 addition & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ required by
* `--latest (-l)`: Show the latest version.
* `--outdated (-o)`: Show the latest version but only for packages that are outdated.
* `--all (-a)`: Show all packages (even those not compatible with current system).
* `--top-level (-T)`: Only show explicitly defined packages.

{{% note %}}
When `--only` is specified, `--with` and `--without` options are ignored.
Expand Down
24 changes: 24 additions & 0 deletions src/poetry/console/commands/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class ShowCommand(GroupCommand, EnvCommand):
"a",
"Show all packages (even those not compatible with current system).",
),
option("top-level", "T", "Show only top-level dependencies."),
]

help = """The show command displays detailed information about a package, or
Expand All @@ -77,6 +78,20 @@ def handle(self) -> int:
if self.option("tree"):
self.init_styles(self.io)

if self.option("top-level"):
if self.option("tree"):
self.line_error(
"<error>Error: Cannot use --tree and --top-level at the same"
" time.</error>"
)
return 1
if package is not None:
self.line_error(
"<error>Error: Cannot use --top-level when displaying a single"
" package.</error>"
)
return 1

if self.option("why"):
if self.option("tree") and package is None:
self.line_error(
Expand Down Expand Up @@ -215,6 +230,7 @@ def _display_packages_information(

show_latest = self.option("latest")
show_all = self.option("all")
show_top_level = self.option("top-level")
width = shutil.get_terminal_size().columns
name_length = version_length = latest_length = required_by_length = 0
latest_packages = {}
Expand Down Expand Up @@ -296,10 +312,18 @@ def _display_packages_information(
write_why = self.option("why") and (why_end_column + 3) <= width
write_description = (why_end_column + 24) <= width

requires = root.all_requires

for locked in locked_packages:
color = "cyan"
name = locked.pretty_name
install_marker = ""

if show_top_level and not any(
locked.is_same_package_as(r) for r in requires
):
continue

if locked not in required_locked_packages:
if not show_all:
continue
Expand Down
121 changes: 121 additions & 0 deletions tests/console/commands/test_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,127 @@ def test_url_dependency_is_not_outdated_by_repository_package(
assert tester.io.fetch_output() == ""


def test_show_top_level(
tester: CommandTester, poetry: Poetry, installed: Repository
) -> None:
poetry.package.add_dependency(Factory.create_dependency("cachy", "^0.2.0"))

cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency(Factory.create_dependency("msgpack-python", ">=0.5 <0.6"))

installed.add_package(cachy2)

poetry.locker.mock_lock_data(
{
"package": [
{
"name": "cachy",
"version": "0.2.0",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
"dependencies": {"msgpack-python": ">=0.5 <0.6"},
},
{
"name": "msgpack-python",
"version": "0.5.1",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
},
],
"metadata": {
"python-versions": "*",
"platform": "*",
"content-hash": "123456789",
"files": {"cachy": [], "msgpack-python": []},
},
}
)

tester.execute("--top-level")

expected = """cachy 0.2.0 \n"""

assert tester.io.fetch_output() == expected


def test_show_top_level_with_explicitly_defined_depenancy(
tester: CommandTester, poetry: Poetry, installed: Repository
) -> None:
poetry.package.add_dependency(Factory.create_dependency("a", "^0.1.0"))
poetry.package.add_dependency(Factory.create_dependency("b", "^0.2.0"))

a = get_package("a", "0.1.0")
a.add_dependency(Factory.create_dependency("b", "0.2.0"))
b = get_package("b", "0.2.0")

installed.add_package(a)
installed.add_package(b)

poetry.locker.mock_lock_data(
{
"package": [
{
"name": "a",
"version": "0.1.0",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
"dependencies": {"b": "0.2.0"},
},
{
"name": "b",
"version": "0.2.0",
"description": "",
"category": "main",
"optional": False,
"platform": "*",
"python-versions": "*",
"checksum": [],
},
],
"metadata": {
"python-versions": "*",
"platform": "*",
"content-hash": "123456789",
"files": {"a": [], "b": []},
},
}
)

tester.execute("--top-level")

expected = """a 0.1.0 \nb 0.2.0 \n"""

assert tester.io.fetch_output() == expected


def test_show_error_top_level_with_tree(
tester: CommandTester,
) -> None:
radoering marked this conversation as resolved.
Show resolved Hide resolved
expected = "Error: Cannot use --tree and --top-level at the same time.\n"
tester.execute("--top-level --tree")
assert tester.io.fetch_error() == expected
assert tester.status_code == 1


def test_show_error_top_level_with_single_package(tester: CommandTester) -> None:
expected = "Error: Cannot use --top-level when displaying a single package.\n"
tester.execute("--top-level some_package_name")
assert tester.io.fetch_error() == expected
assert tester.status_code == 1


@pytest.mark.parametrize(
("project_directory", "required_fixtures"),
[
Expand Down