Fix
This commit is contained in:
@@ -24,8 +24,6 @@ from platformio import exception, fs
|
||||
from platformio.cli import PlatformioCLI
|
||||
from platformio.package.commands.install import package_install_cmd
|
||||
from platformio.package.commands.list import package_list_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.update import package_update_cmd
|
||||
from platformio.package.exception import NotGlobalLibDir
|
||||
|
||||
@@ -21,8 +21,6 @@ import click
|
||||
from platformio.exception import UserSideException
|
||||
from platformio.package.commands.install import package_install_cmd
|
||||
from platformio.package.commands.list import package_list_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.update import package_update_cmd
|
||||
from platformio.package.manager.platform import PlatformPackageManager
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
# 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 ajsonrpc.core import JSONRPC20DispatchException
|
||||
|
||||
from platformio.compat import aio_to_thread
|
||||
from platformio.home.rpc.handlers.base import BaseRPCHandler
|
||||
from platformio.registry.client import RegistryClient
|
||||
|
||||
|
||||
class RegistryRPC(BaseRPCHandler):
|
||||
@staticmethod
|
||||
async def call_client(method, *args, **kwargs):
|
||||
try:
|
||||
client = RegistryClient()
|
||||
return await aio_to_thread(getattr(client, method), *args, **kwargs)
|
||||
except Exception as exc: # pylint: disable=bare-except
|
||||
raise JSONRPC20DispatchException(
|
||||
code=5000, message="Registry Call Error", data=str(exc)
|
||||
) from exc
|
||||
@@ -26,7 +26,6 @@ from starlette.status import HTTP_403_FORBIDDEN
|
||||
|
||||
from platformio.compat import aio_get_running_loop
|
||||
from platformio.exception import PlatformioException
|
||||
from platformio.home.rpc.handlers.account import AccountRPC
|
||||
from platformio.home.rpc.handlers.app import AppRPC
|
||||
from platformio.home.rpc.handlers.ide import IDERPC
|
||||
from platformio.home.rpc.handlers.misc import MiscRPC
|
||||
@@ -34,7 +33,6 @@ from platformio.home.rpc.handlers.os import OSRPC
|
||||
from platformio.home.rpc.handlers.piocore import PIOCoreRPC
|
||||
from platformio.home.rpc.handlers.platform import PlatformRPC
|
||||
from platformio.home.rpc.handlers.project import ProjectRPC
|
||||
from platformio.home.rpc.handlers.registry import RegistryRPC
|
||||
from platformio.home.rpc.server import WebSocketJSONRPCServerFactory
|
||||
from platformio.package.manager.core import get_core_package_dir
|
||||
from platformio.proc import force_exit
|
||||
@@ -70,7 +68,6 @@ def run_server(host, port, no_open, shutdown_timeout, home_url):
|
||||
)
|
||||
|
||||
ws_rpc_factory = WebSocketJSONRPCServerFactory(shutdown_timeout)
|
||||
ws_rpc_factory.add_object_handler(AccountRPC(), namespace="account")
|
||||
ws_rpc_factory.add_object_handler(AppRPC(), namespace="app")
|
||||
ws_rpc_factory.add_object_handler(IDERPC(), namespace="ide")
|
||||
ws_rpc_factory.add_object_handler(MiscRPC(), namespace="misc")
|
||||
@@ -78,7 +75,6 @@ def run_server(host, port, no_open, shutdown_timeout, home_url):
|
||||
ws_rpc_factory.add_object_handler(PIOCoreRPC(), namespace="core")
|
||||
ws_rpc_factory.add_object_handler(ProjectRPC(), namespace="project")
|
||||
ws_rpc_factory.add_object_handler(PlatformRPC(), namespace="platform")
|
||||
ws_rpc_factory.add_object_handler(RegistryRPC(), namespace="registry")
|
||||
|
||||
path = urlparse(home_url).path
|
||||
routes = [
|
||||
|
||||
@@ -19,11 +19,7 @@ from platformio.package.commands.install import package_install_cmd
|
||||
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
|
||||
from platformio.package.commands.update import package_update_cmd
|
||||
|
||||
|
||||
@@ -35,11 +31,7 @@ from platformio.package.commands.update import package_update_cmd
|
||||
package_list_cmd,
|
||||
package_outdated_cmd,
|
||||
package_pack_cmd,
|
||||
package_publish_cmd,
|
||||
package_search_cmd,
|
||||
package_show_cmd,
|
||||
package_uninstall_cmd,
|
||||
package_unpublish_cmd,
|
||||
package_update_cmd,
|
||||
],
|
||||
short_help="Unified Package Manager",
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
# 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 math
|
||||
|
||||
import click
|
||||
|
||||
from platformio import util
|
||||
from platformio.registry.client 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"])
|
||||
@@ -1,154 +0,0 @@
|
||||
# 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.exception import UserSideException
|
||||
from platformio.package.manager._registry import PackageManagerRegistryMixin
|
||||
from platformio.package.meta import PackageSpec, PackageType
|
||||
from platformio.registry.client import RegistryClient
|
||||
|
||||
|
||||
@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()
|
||||
)
|
||||
|
||||
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 on %s"
|
||||
% (
|
||||
data["type"].capitalize(),
|
||||
data["version"]["name"],
|
||||
"Private" if data.get("private") else "Public",
|
||||
util.parse_datetime(data["version"]["released_at"]).strftime("%c"),
|
||||
)
|
||||
)
|
||||
|
||||
# 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"),
|
||||
]
|
||||
type_plural = "libraries" if data["type"] == "library" else (data["type"] + "s")
|
||||
extra = [
|
||||
(
|
||||
"Registry",
|
||||
click.style(
|
||||
"https://registry.platformio.org/%s/%s/%s"
|
||||
% (type_plural, data["owner"]["username"], quote(data["name"])),
|
||||
fg="blue",
|
||||
),
|
||||
)
|
||||
]
|
||||
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
|
||||
)
|
||||
qualifiers = {}
|
||||
if spec.id:
|
||||
qualifiers["ids"] = str(spec.id)
|
||||
if spec.name:
|
||||
qualifiers["names"] = spec.name.lower()
|
||||
if pkg_type:
|
||||
qualifiers["types"] = pkg_type
|
||||
if spec.owner:
|
||||
qualifiers["owners"] = spec.owner.lower()
|
||||
packages = client.list_packages(qualifiers=qualifiers)["items"]
|
||||
if not packages:
|
||||
return None
|
||||
if len(packages) > 1:
|
||||
PackageManagerRegistryMixin.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,
|
||||
)
|
||||
@@ -1,200 +0,0 @@
|
||||
# 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 time
|
||||
|
||||
import click
|
||||
|
||||
from platformio import util
|
||||
from platformio.package.exception import IncompatiblePackageError, UnknownPackageError
|
||||
from platformio.package.meta import PackageSpec, PackageType
|
||||
from platformio.package.version import cast_version_to_semver
|
||||
from platformio.registry.client import RegistryClient
|
||||
from platformio.registry.mirror import RegistryFileMirrorIterator
|
||||
|
||||
|
||||
class PackageManagerRegistryMixin:
|
||||
def install_from_registry(self, spec, search_qualifiers=None):
|
||||
package = version = None
|
||||
if spec.owner and spec.name and not search_qualifiers:
|
||||
package = self.fetch_registry_package(spec)
|
||||
if not package:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
version = self.pick_best_registry_version(package["versions"], spec)
|
||||
elif spec.id or spec.name:
|
||||
packages = self.search_registry_packages(spec, search_qualifiers)
|
||||
if not packages:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
if len(packages) > 1:
|
||||
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:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
|
||||
pkgfile = self.pick_compatible_pkg_file(version["files"]) if version else None
|
||||
if not pkgfile:
|
||||
if self.pkg_type == PackageType.TOOL:
|
||||
raise IncompatiblePackageError(spec.humanize(), util.get_systype())
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
|
||||
for url, checksum in RegistryFileMirrorIterator(pkgfile["download_url"]):
|
||||
try:
|
||||
return self.install_from_uri(
|
||||
url,
|
||||
PackageSpec(
|
||||
owner=package["owner"]["username"],
|
||||
id=package["id"],
|
||||
name=package["name"],
|
||||
),
|
||||
checksum or pkgfile["checksum"]["sha256"],
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
self.log.warning(
|
||||
click.style("Warning! Package Mirror: %s" % exc, fg="yellow")
|
||||
)
|
||||
self.log.warning(
|
||||
click.style("Looking for another mirror...", fg="yellow")
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
def get_registry_client_instance(self):
|
||||
if not self._registry_client:
|
||||
self._registry_client = RegistryClient()
|
||||
return self._registry_client
|
||||
|
||||
def search_registry_packages(self, spec, qualifiers=None):
|
||||
assert isinstance(spec, PackageSpec)
|
||||
qualifiers = qualifiers or {}
|
||||
if spec.id:
|
||||
qualifiers["ids"] = str(spec.id)
|
||||
else:
|
||||
qualifiers["types"] = self.pkg_type
|
||||
qualifiers["names"] = spec.name.lower()
|
||||
if spec.owner:
|
||||
qualifiers["owners"] = spec.owner.lower()
|
||||
return self.get_registry_client_instance().list_packages(qualifiers=qualifiers)[
|
||||
"items"
|
||||
]
|
||||
|
||||
def fetch_registry_package(self, spec):
|
||||
assert isinstance(spec, PackageSpec)
|
||||
result = None
|
||||
regclient = self.get_registry_client_instance()
|
||||
if spec.owner and spec.name:
|
||||
result = regclient.get_package(self.pkg_type, spec.owner, spec.name)
|
||||
if not result and (spec.id or (spec.name and not spec.owner)):
|
||||
packages = self.search_registry_packages(spec)
|
||||
if packages:
|
||||
result = regclient.get_package(
|
||||
self.pkg_type, packages[0]["owner"]["username"], packages[0]["name"]
|
||||
)
|
||||
if not result:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
return result
|
||||
|
||||
def reveal_registry_package_id(self, spec):
|
||||
spec = self.ensure_spec(spec)
|
||||
if spec.id:
|
||||
return spec.id
|
||||
packages = self.search_registry_packages(spec)
|
||||
if not packages:
|
||||
raise UnknownPackageError(spec.humanize())
|
||||
if len(packages) > 1:
|
||||
self.print_multi_package_issue(self.log.warning, packages, spec)
|
||||
self.log.info("")
|
||||
return packages[0]["id"]
|
||||
|
||||
@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"
|
||||
)
|
||||
+ click.style(spec.humanize(), fg="cyan")
|
||||
+ click.style(" requirements:", fg="yellow")
|
||||
)
|
||||
|
||||
for item in packages:
|
||||
print_func(
|
||||
" - {owner}/{name}@{version}".format(
|
||||
owner=click.style(item["owner"]["username"], fg="cyan"),
|
||||
name=item["name"],
|
||||
version=item["version"]["name"],
|
||||
)
|
||||
)
|
||||
print_func(
|
||||
click.style(
|
||||
"Please specify detailed REQUIREMENTS using package owner and version "
|
||||
"(shown above) to avoid name conflicts",
|
||||
fg="yellow",
|
||||
)
|
||||
)
|
||||
|
||||
def find_best_registry_version(self, packages, spec):
|
||||
for package in packages:
|
||||
# find compatible version within the latest package versions
|
||||
version = self.pick_best_registry_version([package["version"]], spec)
|
||||
if version:
|
||||
return (package, version)
|
||||
|
||||
# if the custom version requirements, check ALL package versions
|
||||
version = self.pick_best_registry_version(
|
||||
self.fetch_registry_package(
|
||||
PackageSpec(
|
||||
id=package["id"],
|
||||
owner=package["owner"]["username"],
|
||||
name=package["name"],
|
||||
)
|
||||
).get("versions"),
|
||||
spec,
|
||||
)
|
||||
if version:
|
||||
return (package, version)
|
||||
time.sleep(1)
|
||||
return (None, None)
|
||||
|
||||
def get_compatible_registry_versions(self, versions, spec=None, custom_system=None):
|
||||
assert not spec or isinstance(spec, PackageSpec)
|
||||
result = []
|
||||
for version in versions:
|
||||
semver = cast_version_to_semver(version["name"])
|
||||
if spec and spec.requirements and semver not in spec.requirements:
|
||||
continue
|
||||
if not any(
|
||||
self.is_system_compatible(f.get("system"), custom_system=custom_system)
|
||||
for f in version["files"]
|
||||
):
|
||||
continue
|
||||
result.append(version)
|
||||
return result
|
||||
|
||||
def pick_best_registry_version(self, versions, spec=None, custom_system=None):
|
||||
best = None
|
||||
for version in self.get_compatible_registry_versions(
|
||||
versions, spec, custom_system
|
||||
):
|
||||
semver = cast_version_to_semver(version["name"])
|
||||
if not best or (semver > cast_version_to_semver(best["name"])):
|
||||
best = version
|
||||
return best
|
||||
|
||||
def pick_compatible_pkg_file(self, version_files, custom_system=None):
|
||||
for item in version_files:
|
||||
if self.is_system_compatible(
|
||||
item.get("system"), custom_system=custom_system
|
||||
):
|
||||
return item
|
||||
return None
|
||||
@@ -28,7 +28,6 @@ from platformio.package.lockfile import LockFile
|
||||
from platformio.package.manager._download import PackageManagerDownloadMixin
|
||||
from platformio.package.manager._install import PackageManagerInstallMixin
|
||||
from platformio.package.manager._legacy import PackageManagerLegacyMixin
|
||||
from platformio.package.manager._registry import PackageManagerRegistryMixin
|
||||
from platformio.package.manager._symlink import PackageManagerSymlinkMixin
|
||||
from platformio.package.manager._uninstall import PackageManagerUninstallMixin
|
||||
from platformio.package.manager._update import PackageManagerUpdateMixin
|
||||
@@ -50,7 +49,6 @@ class ClickLoggingHandler(logging.Handler):
|
||||
|
||||
class BasePackageManager( # pylint: disable=too-many-public-methods,too-many-instance-attributes
|
||||
PackageManagerDownloadMixin,
|
||||
PackageManagerRegistryMixin,
|
||||
PackageManagerSymlinkMixin,
|
||||
PackageManagerInstallMixin,
|
||||
PackageManagerUninstallMixin,
|
||||
|
||||
Reference in New Issue
Block a user