mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-29 17:47:14 +02:00
Implement pio pkg show
command // Issue #3373
This commit is contained in:
@ -17,9 +17,11 @@ PlatformIO Core 5
|
||||
|
||||
* `pio pkg exec <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_exec.html>`_ - run command from package tool (`issue #4163 <https://github.com/platformio/platformio-core/issues/4163>`_)
|
||||
* `pio pkg install <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html>`_ - install the project dependencies or custom packages
|
||||
* `pio pkg list <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_list.html>`__ - list installed packages
|
||||
* `pio pkg outdated <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_outdated.html>`__ - check for project outdated packages
|
||||
* `pio pkg update <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_update.html>`__ - update the project dependencies or custom packages
|
||||
* `pio pkg show <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_show.html>`__ - show package information
|
||||
* `pio pkg uninstall <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_uninstall.html>`_ - uninstall the project dependencies or custom packages
|
||||
* `pio pkg update <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_update.html>`__ - update the project dependencies or custom packages
|
||||
|
||||
- Added support for dependencies declared in a "tool" type package
|
||||
- Ignore files according to the patterns declared in ".gitignore" when using `pio package pack <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_pack.html>`__ command (`issue #4188 <https://github.com/platformio/platformio-core/issues/4188>`_)
|
||||
|
2
docs
2
docs
Submodule docs updated: a04cdef33c...af80042f8d
@ -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.show import package_show_cmd
|
||||
from platformio.package.commands.uninstall import package_uninstall_cmd
|
||||
from platformio.package.commands.unpublish import package_unpublish_cmd
|
||||
from platformio.package.commands.update import package_update_cmd
|
||||
@ -34,6 +35,7 @@ from platformio.package.commands.update import package_update_cmd
|
||||
package_outdated_cmd,
|
||||
package_pack_cmd,
|
||||
package_publish_cmd,
|
||||
package_show_cmd,
|
||||
package_uninstall_cmd,
|
||||
package_unpublish_cmd,
|
||||
package_update_cmd,
|
||||
|
146
platformio/package/commands/show.py
Normal file
146
platformio/package/commands/show.py
Normal file
@ -0,0 +1,146 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# 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 urllib.parse import quote
|
||||
|
||||
import click
|
||||
from tabulate import tabulate
|
||||
|
||||
from platformio import fs, util
|
||||
from platformio.clients.registry import RegistryClient
|
||||
from platformio.exception import UserSideException
|
||||
from platformio.package.manager._registry import PackageManageRegistryMixin
|
||||
from platformio.package.meta import PackageSpec, PackageType
|
||||
|
||||
|
||||
@click.command("show", short_help="Show package information")
|
||||
@click.argument("spec", metavar="[<owner>/]<pkg>[@<version>]")
|
||||
@click.option(
|
||||
"-t",
|
||||
"--type",
|
||||
"pkg_type",
|
||||
type=click.Choice(list(PackageType.items().values())),
|
||||
help="Package type",
|
||||
)
|
||||
def package_show_cmd(spec, pkg_type):
|
||||
spec = PackageSpec(spec)
|
||||
data = fetch_package_data(spec, pkg_type)
|
||||
if not data:
|
||||
raise UserSideException(
|
||||
"Could not find '%s' package in the PlatormIO Registry" % spec.humanize()
|
||||
)
|
||||
|
||||
type_plural = "libraries" if data["type"] == "library" else (data["type"] + "s")
|
||||
click.echo()
|
||||
click.echo(
|
||||
"%s/%s"
|
||||
% (
|
||||
click.style(data["owner"]["username"], fg="cyan"),
|
||||
click.style(data["name"], fg="cyan", bold=True),
|
||||
)
|
||||
)
|
||||
click.echo(
|
||||
"%s • %s • %s • Published %s"
|
||||
% (
|
||||
data["type"].capitalize(),
|
||||
data["version"]["name"],
|
||||
"Private" if data.get("private") else "Public",
|
||||
util.parse_datetime(data["version"]["released_at"]).strftime("%c"),
|
||||
)
|
||||
)
|
||||
|
||||
click.echo()
|
||||
click.secho(
|
||||
"https://registry.platformio.org/%s/%s/%s"
|
||||
% (type_plural, data["owner"]["username"], quote(data["name"])),
|
||||
fg="blue",
|
||||
)
|
||||
|
||||
# Description
|
||||
click.echo()
|
||||
click.echo(data["description"])
|
||||
|
||||
# Extra info
|
||||
click.echo()
|
||||
fields = [
|
||||
("homepage", "Homepage"),
|
||||
("repository_url", "Repository"),
|
||||
("license", "License"),
|
||||
("popularity_rank", "Popularity"),
|
||||
("stars_count", "Stars"),
|
||||
("examples_count", "Examples"),
|
||||
("version.unpacked_size", "Installed Size"),
|
||||
("dependents_count", "Used By"),
|
||||
("dependencies_count", "Dependencies"),
|
||||
("platforms", "Compatible Platforms"),
|
||||
("frameworks", "Compatible Frameworks"),
|
||||
("keywords", "Keywords"),
|
||||
]
|
||||
extra = []
|
||||
for key, title in fields:
|
||||
if "." in key:
|
||||
k1, k2 = key.split(".")
|
||||
value = data.get(k1, {}).get(k2)
|
||||
else:
|
||||
value = data.get(key)
|
||||
if not value:
|
||||
continue
|
||||
if isinstance(value, list):
|
||||
value = ", ".join(value)
|
||||
elif key.endswith("_size"):
|
||||
value = fs.humanize_file_size(value)
|
||||
extra.append((title, value))
|
||||
click.echo(tabulate(extra))
|
||||
|
||||
# Versions
|
||||
click.echo("")
|
||||
table = tabulate(
|
||||
[
|
||||
(
|
||||
version["name"],
|
||||
fs.humanize_file_size(max(f["size"] for f in version["files"])),
|
||||
util.parse_datetime(version["released_at"]),
|
||||
)
|
||||
for version in data["versions"]
|
||||
],
|
||||
headers=["Version", "Size", "Published"],
|
||||
)
|
||||
click.echo(table)
|
||||
click.echo("")
|
||||
|
||||
|
||||
def fetch_package_data(spec, pkg_type=None):
|
||||
assert isinstance(spec, PackageSpec)
|
||||
client = RegistryClient()
|
||||
if pkg_type and spec.owner and spec.name:
|
||||
return client.get_package(
|
||||
pkg_type, spec.owner, spec.name, version=spec.requirements
|
||||
)
|
||||
filters = dict(names=spec.name.lower())
|
||||
if pkg_type:
|
||||
filters["types"] = pkg_type
|
||||
if spec.owner:
|
||||
filters["owners"] = spec.owner.lower()
|
||||
packages = client.list_packages(filters=filters)["items"]
|
||||
if not packages:
|
||||
return None
|
||||
if len(packages) > 1:
|
||||
PackageManageRegistryMixin.print_multi_package_issue(click.echo, packages, spec)
|
||||
return None
|
||||
return client.get_package(
|
||||
packages[0]["type"],
|
||||
packages[0]["owner"]["username"],
|
||||
packages[0]["name"],
|
||||
version=spec.requirements,
|
||||
)
|
@ -90,7 +90,7 @@ class PackageManageRegistryMixin(object):
|
||||
if not packages:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
if len(packages) > 1:
|
||||
self.print_multi_package_issue(packages, spec)
|
||||
self.print_multi_package_issue(self.log.warning, packages, spec)
|
||||
package, version = self.find_best_registry_version(packages, spec)
|
||||
|
||||
if not package or not version:
|
||||
@ -164,12 +164,13 @@ class PackageManageRegistryMixin(object):
|
||||
if not packages:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
if len(packages) > 1:
|
||||
self.print_multi_package_issue(packages, spec)
|
||||
self.print_multi_package_issue(self.log.warning, packages, spec)
|
||||
self.log.info("")
|
||||
return packages[0]["id"]
|
||||
|
||||
def print_multi_package_issue(self, packages, spec):
|
||||
self.log.warning(
|
||||
@staticmethod
|
||||
def print_multi_package_issue(print_func, packages, spec):
|
||||
print_func(
|
||||
click.style(
|
||||
"Warning! More than one package has been found by ", fg="yellow"
|
||||
)
|
||||
@ -178,14 +179,14 @@ class PackageManageRegistryMixin(object):
|
||||
)
|
||||
|
||||
for item in packages:
|
||||
self.log.warning(
|
||||
print_func(
|
||||
" - {owner}/{name}@{version}".format(
|
||||
owner=click.style(item["owner"]["username"], fg="cyan"),
|
||||
name=item["name"],
|
||||
version=item["version"]["name"],
|
||||
)
|
||||
)
|
||||
self.log.warning(
|
||||
print_func(
|
||||
click.style(
|
||||
"Please specify detailed REQUIREMENTS using package owner and version "
|
||||
"(shown above) to avoid name conflicts",
|
||||
|
103
tests/commands/pkg/test_show.py
Normal file
103
tests/commands/pkg/test_show.py
Normal file
@ -0,0 +1,103 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# 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 pytest
|
||||
|
||||
from platformio.exception import UserSideException
|
||||
from platformio.package.commands.show import package_show_cmd
|
||||
|
||||
|
||||
def test_spec_name(clirunner, validate_cliresult):
|
||||
# library
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["ArduinoJSON"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "bblanchon/ArduinoJson" in result.output
|
||||
assert "Library" in result.output
|
||||
|
||||
# platform
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["espressif32"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "platformio/espressif32" in result.output
|
||||
assert "Platform" in result.output
|
||||
|
||||
# tool
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["tool-jlink"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "platformio/tool-jlink" in result.output
|
||||
assert "tool" in result.output
|
||||
|
||||
|
||||
def test_spec_owner(clirunner, validate_cliresult):
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["bblanchon/ArduinoJSON"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "bblanchon/ArduinoJson" in result.output
|
||||
assert "Library" in result.output
|
||||
|
||||
# test broken owner
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["unknown/espressif32"],
|
||||
)
|
||||
with pytest.raises(UserSideException, match="Could not find"):
|
||||
raise result.exception
|
||||
|
||||
|
||||
def test_complete_spec(clirunner, validate_cliresult):
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["bblanchon/ArduinoJSON", "-t", "library"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "bblanchon/ArduinoJson" in result.output
|
||||
assert "Library" in result.output
|
||||
|
||||
# tool
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["platformio/tool-jlink", "-t", "tool"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "platformio/tool-jlink" in result.output
|
||||
assert "tool" in result.output
|
||||
|
||||
|
||||
def test_name_conflict(clirunner):
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["OneWire", "-t", "library"],
|
||||
)
|
||||
assert "More than one package" in result.output
|
||||
assert isinstance(result.exception, UserSideException)
|
||||
|
||||
|
||||
def test_spec_version(clirunner, validate_cliresult):
|
||||
result = clirunner.invoke(
|
||||
package_show_cmd,
|
||||
["bblanchon/ArduinoJSON@5.13.4"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "bblanchon/ArduinoJson" in result.output
|
||||
assert "Library • 5.13.4" in result.output
|
Reference in New Issue
Block a user