From a6e12532f879f3168ed5086d6706db87de3b48d7 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 30 Mar 2022 17:32:05 +0300 Subject: [PATCH] Implement `pio pkg search` command // Issue #3373 --- HISTORY.rst | 1 + docs | 2 +- platformio/commands/pkg.py | 2 + platformio/package/commands/search.py | 77 +++++++++++++++++++++++++++ tests/commands/pkg/test_search.py | 58 ++++++++++++++++++++ 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 platformio/package/commands/search.py create mode 100644 tests/commands/pkg/test_search.py diff --git a/HISTORY.rst b/HISTORY.rst index 09c548ff..489b9e26 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,6 +19,7 @@ PlatformIO Core 5 * `pio pkg install `_ - install the project dependencies or custom packages * `pio pkg list `__ - list installed packages * `pio pkg outdated `__ - check for project outdated packages + * `pio pkg search `__ - search for packages * `pio pkg show `__ - show package information * `pio pkg uninstall `_ - uninstall the project dependencies or custom packages * `pio pkg update `__ - update the project dependencies or custom packages diff --git a/docs b/docs index d8a27471..e672ed7a 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit d8a27471c7471778edd33fdd2d163f29dec6ce16 +Subproject commit e672ed7a4ae8f4cb962cb9784ce3734b2af94d30 diff --git a/platformio/commands/pkg.py b/platformio/commands/pkg.py index d9c1fcd1..1ef3978d 100644 --- a/platformio/commands/pkg.py +++ b/platformio/commands/pkg.py @@ -20,6 +20,7 @@ from platformio.package.commands.list import package_list_cmd from platformio.package.commands.outdated import package_outdated_cmd from platformio.package.commands.pack import package_pack_cmd from platformio.package.commands.publish import package_publish_cmd +from platformio.package.commands.search import package_search_cmd from platformio.package.commands.show import package_show_cmd from platformio.package.commands.uninstall import package_uninstall_cmd from platformio.package.commands.unpublish import package_unpublish_cmd @@ -35,6 +36,7 @@ from platformio.package.commands.update import package_update_cmd package_outdated_cmd, package_pack_cmd, package_publish_cmd, + package_search_cmd, package_show_cmd, package_uninstall_cmd, package_unpublish_cmd, diff --git a/platformio/package/commands/search.py b/platformio/package/commands/search.py new file mode 100644 index 00000000..57ec76ec --- /dev/null +++ b/platformio/package/commands/search.py @@ -0,0 +1,77 @@ +# Copyright (c) 2014-present PlatformIO +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math + +import click + +from platformio import util +from platformio.clients.registry import RegistryClient + + +@click.command("search", short_help="Search for packages") +@click.argument("query") +@click.option("-p", "--page", type=click.IntRange(min=1)) +@click.option( + "-s", + "--sort", + type=click.Choice(["relevance", "popularity", "trending", "added", "updated"]), +) +def package_search_cmd(query, page, sort): + client = RegistryClient() + result = client.list_packages(query, page=page, sort=sort) + if not result["total"]: + click.secho("Nothing has been found by your request", fg="yellow") + click.echo( + "Try a less-specific search or use truncation (or wildcard) operator *" + ) + return + print_search_result(result) + + +def print_search_result(result): + click.echo( + "Found %d packages (page %d of %d)" + % ( + result["total"], + result["page"], + math.ceil(result["total"] / result["limit"]), + ) + ) + for item in result["items"]: + click.echo() + print_search_item(item) + + +def print_search_item(item): + click.echo( + "%s/%s" + % ( + click.style(item["owner"]["username"], fg="cyan"), + click.style(item["name"], fg="cyan", bold=True), + ) + ) + click.echo( + "%s • %s • Published on %s" + % ( + item["type"].capitalize() + if item["tier"] == "community" + else click.style( + ("%s %s" % (item["tier"], item["type"])).title(), bold=True + ), + item["version"]["name"], + util.parse_datetime(item["version"]["released_at"]).strftime("%c"), + ) + ) + click.echo(item["description"]) diff --git a/tests/commands/pkg/test_search.py b/tests/commands/pkg/test_search.py new file mode 100644 index 00000000..284f4363 --- /dev/null +++ b/tests/commands/pkg/test_search.py @@ -0,0 +1,58 @@ +# Copyright (c) 2014-present PlatformIO +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from platformio.package.commands.search import package_search_cmd + + +def test_empty_query(clirunner, validate_cliresult): + result = clirunner.invoke( + package_search_cmd, + [""], + ) + validate_cliresult(result) + assert all(t in result.output for t in ("Found", "Official", "page 1 of")) + + +def test_pagination(clirunner, validate_cliresult): + result = clirunner.invoke( + package_search_cmd, + ["type:tool"], + ) + validate_cliresult(result) + assert all(t in result.output for t in ("Verified Tool", "page 1 of")) + + result = clirunner.invoke( + package_search_cmd, + ["type:tool", "-p", "10"], + ) + validate_cliresult(result) + assert all(t in result.output for t in ("Tool", "page 10 of")) + + +def test_sorting(clirunner, validate_cliresult): + result = clirunner.invoke( + package_search_cmd, + ["OneWire", "-s", "popularity"], + ) + validate_cliresult(result) + assert "paulstoffregen/OneWire" in result.output + + +def test_not_found(clirunner, validate_cliresult): + result = clirunner.invoke( + package_search_cmd, + ["name:unknown-package"], + ) + validate_cliresult(result) + assert "Nothing has been found" in result.output