mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 10:07: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 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 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 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 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
|
- 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>`_)
|
- 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.outdated import package_outdated_cmd
|
||||||
from platformio.package.commands.pack import package_pack_cmd
|
from platformio.package.commands.pack import package_pack_cmd
|
||||||
from platformio.package.commands.publish import package_publish_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.uninstall import package_uninstall_cmd
|
||||||
from platformio.package.commands.unpublish import package_unpublish_cmd
|
from platformio.package.commands.unpublish import package_unpublish_cmd
|
||||||
from platformio.package.commands.update import package_update_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_outdated_cmd,
|
||||||
package_pack_cmd,
|
package_pack_cmd,
|
||||||
package_publish_cmd,
|
package_publish_cmd,
|
||||||
|
package_show_cmd,
|
||||||
package_uninstall_cmd,
|
package_uninstall_cmd,
|
||||||
package_unpublish_cmd,
|
package_unpublish_cmd,
|
||||||
package_update_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:
|
if not packages:
|
||||||
raise UnknownPackageError(spec.humanize())
|
raise UnknownPackageError(spec.humanize())
|
||||||
if len(packages) > 1:
|
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)
|
package, version = self.find_best_registry_version(packages, spec)
|
||||||
|
|
||||||
if not package or not version:
|
if not package or not version:
|
||||||
@ -164,12 +164,13 @@ class PackageManageRegistryMixin(object):
|
|||||||
if not packages:
|
if not packages:
|
||||||
raise UnknownPackageError(spec.humanize())
|
raise UnknownPackageError(spec.humanize())
|
||||||
if len(packages) > 1:
|
if len(packages) > 1:
|
||||||
self.print_multi_package_issue(packages, spec)
|
self.print_multi_package_issue(self.log.warning, packages, spec)
|
||||||
self.log.info("")
|
self.log.info("")
|
||||||
return packages[0]["id"]
|
return packages[0]["id"]
|
||||||
|
|
||||||
def print_multi_package_issue(self, packages, spec):
|
@staticmethod
|
||||||
self.log.warning(
|
def print_multi_package_issue(print_func, packages, spec):
|
||||||
|
print_func(
|
||||||
click.style(
|
click.style(
|
||||||
"Warning! More than one package has been found by ", fg="yellow"
|
"Warning! More than one package has been found by ", fg="yellow"
|
||||||
)
|
)
|
||||||
@ -178,14 +179,14 @@ class PackageManageRegistryMixin(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for item in packages:
|
for item in packages:
|
||||||
self.log.warning(
|
print_func(
|
||||||
" - {owner}/{name}@{version}".format(
|
" - {owner}/{name}@{version}".format(
|
||||||
owner=click.style(item["owner"]["username"], fg="cyan"),
|
owner=click.style(item["owner"]["username"], fg="cyan"),
|
||||||
name=item["name"],
|
name=item["name"],
|
||||||
version=item["version"]["name"],
|
version=item["version"]["name"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.log.warning(
|
print_func(
|
||||||
click.style(
|
click.style(
|
||||||
"Please specify detailed REQUIREMENTS using package owner and version "
|
"Please specify detailed REQUIREMENTS using package owner and version "
|
||||||
"(shown above) to avoid name conflicts",
|
"(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