Use new unified package API for deprecated pio lib command // Resolve #4198

This commit is contained in:
Ivan Kravets
2022-06-20 14:24:09 +03:00
parent 8cbe7bc7a6
commit 5142feba7a
9 changed files with 170 additions and 487 deletions

View File

@ -17,16 +17,18 @@
import json import json
import logging import logging
import os import os
import time
from urllib.parse import quote
import click import click
from tabulate import tabulate
from platformio import exception, fs, util from platformio import exception, fs
from platformio.cli import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.lib.helpers import get_builtin_libs, save_project_libdeps from platformio.package.commands.install import package_install_cmd
from platformio.package.exception import NotGlobalLibDir, UnknownPackageError 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
from platformio.package.manager.library import LibraryPackageManager from platformio.package.manager.library import LibraryPackageManager
from platformio.package.meta import PackageItem, PackageSpec from platformio.package.meta import PackageItem, PackageSpec
from platformio.proc import is_ci from platformio.proc import is_ci
@ -43,6 +45,20 @@ def get_project_global_lib_dir():
return ProjectConfig.get_instance().get("platformio", "globallib_dir") return ProjectConfig.get_instance().get("platformio", "globallib_dir")
def invoke_command(ctx, cmd, **kwargs):
input_dirs = ctx.meta.get(CTX_META_INPUT_DIRS_KEY, [])
project_environments = ctx.meta[CTX_META_PROJECT_ENVIRONMENTS_KEY]
for input_dir in input_dirs:
cmd_kwargs = kwargs.copy()
if is_platformio_project(input_dir):
cmd_kwargs["project_dir"] = input_dir
cmd_kwargs["environments"] = project_environments
else:
cmd_kwargs["global"] = True
cmd_kwargs["storage_dir"] = input_dir
ctx.invoke(cmd, **cmd_kwargs)
@click.group(short_help="Library manager", hidden=True) @click.group(short_help="Library manager", hidden=True)
@click.option( @click.option(
"-d", "-d",
@ -146,55 +162,14 @@ def lib_install( # pylint: disable=too-many-arguments,unused-argument
"the next releases. \nPlease use `pio pkg install` instead.\n", "the next releases. \nPlease use `pio pkg install` instead.\n",
fg="yellow", fg="yellow",
) )
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY] return invoke_command(
storage_libdeps = ctx.meta.get(CTX_META_STORAGE_LIBDEPS_KEY, []) ctx,
package_install_cmd,
installed_pkgs = {} libraries=libraries,
for storage_dir in storage_dirs: no_save=not save,
if not silent and (libraries or storage_dir in storage_libdeps): force=force,
print_storage_header(storage_dirs, storage_dir) silent=silent,
lm = LibraryPackageManager(storage_dir) )
lm.set_log_level(logging.WARN if silent else logging.DEBUG)
if libraries:
installed_pkgs = {
library: lm.install(library, force=force) for library in libraries
}
elif storage_dir in storage_libdeps:
for library in storage_libdeps[storage_dir]:
lm.install(library, force=force)
if save and installed_pkgs:
_save_deps(ctx, installed_pkgs)
def _save_deps(ctx, pkgs, action="add"):
specs = []
for library, pkg in pkgs.items():
spec = PackageSpec(library)
if spec.external:
specs.append(spec)
else:
specs.append(
PackageSpec(
owner=pkg.metadata.spec.owner,
name=pkg.metadata.spec.name,
requirements=spec.requirements
or (
("^%s" % pkg.metadata.version)
if not pkg.metadata.version.build
else pkg.metadata.version
),
)
)
input_dirs = ctx.meta.get(CTX_META_INPUT_DIRS_KEY, [])
project_environments = ctx.meta[CTX_META_PROJECT_ENVIRONMENTS_KEY]
for input_dir in input_dirs:
if not is_platformio_project(input_dir):
continue
save_project_libdeps(input_dir, specs, project_environments, action=action)
@cli.command("uninstall", short_help="Remove libraries") @cli.command("uninstall", short_help="Remove libraries")
@ -214,16 +189,13 @@ def lib_uninstall(ctx, libraries, save, silent):
"the next releases. \nPlease use `pio pkg uninstall` instead.\n", "the next releases. \nPlease use `pio pkg uninstall` instead.\n",
fg="yellow", fg="yellow",
) )
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY] invoke_command(
uninstalled_pkgs = {} ctx,
for storage_dir in storage_dirs: package_uninstall_cmd,
print_storage_header(storage_dirs, storage_dir) libraries=libraries,
lm = LibraryPackageManager(storage_dir) no_save=not save,
lm.set_log_level(logging.WARN if silent else logging.DEBUG) silent=silent,
uninstalled_pkgs = {library: lm.uninstall(library) for library in libraries} )
if save and uninstalled_pkgs:
_save_deps(ctx, uninstalled_pkgs, action="remove")
@cli.command("update", short_help="Update installed libraries") @cli.command("update", short_help="Update installed libraries")
@ -255,60 +227,51 @@ def lib_update( # pylint: disable=too-many-arguments
"the next releases. \nPlease use `pio pkg update` instead.\n", "the next releases. \nPlease use `pio pkg update` instead.\n",
fg="yellow", fg="yellow",
) )
return invoke_command(
ctx,
package_update_cmd,
libraries=libraries,
silent=silent,
)
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY] storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY]
json_result = {} json_result = {}
for storage_dir in storage_dirs: for storage_dir in storage_dirs:
if not json_output:
print_storage_header(storage_dirs, storage_dir)
lib_deps = ctx.meta.get(CTX_META_STORAGE_LIBDEPS_KEY, {}).get(storage_dir, []) lib_deps = ctx.meta.get(CTX_META_STORAGE_LIBDEPS_KEY, {}).get(storage_dir, [])
lm = LibraryPackageManager(storage_dir) lm = LibraryPackageManager(storage_dir)
lm.set_log_level(logging.WARN if silent else logging.DEBUG) lm.set_log_level(logging.WARN if silent else logging.DEBUG)
_libraries = libraries or lib_deps or lm.get_installed() _libraries = libraries or lib_deps or lm.get_installed()
if only_check and json_output: result = []
result = [] for library in _libraries:
for library in _libraries: spec = None
spec = None pkg = None
pkg = None if isinstance(library, PackageItem):
if isinstance(library, PackageItem): pkg = library
pkg = library else:
else: spec = PackageSpec(library)
spec = PackageSpec(library) pkg = lm.get_package(spec)
pkg = lm.get_package(spec) if not pkg:
if not pkg: continue
continue outdated = lm.outdated(pkg, spec)
outdated = lm.outdated(pkg, spec) if not outdated.is_outdated(allow_incompatible=True):
if not outdated.is_outdated(allow_incompatible=True): continue
continue manifest = lm.legacy_load_manifest(pkg)
manifest = lm.legacy_load_manifest(pkg) manifest["versionWanted"] = (
manifest["versionWanted"] = ( str(outdated.wanted) if outdated.wanted else None
str(outdated.wanted) if outdated.wanted else None
)
manifest["versionLatest"] = (
str(outdated.latest) if outdated.latest else None
)
result.append(manifest)
json_result[storage_dir] = result
else:
for library in _libraries:
to_spec = (
None if isinstance(library, PackageItem) else PackageSpec(library)
)
try:
lm.update(library, to_spec=to_spec)
except UnknownPackageError as e:
if library not in lib_deps:
raise e
if json_output:
return click.echo(
json.dumps(
json_result[storage_dirs[0]] if len(storage_dirs) == 1 else json_result
) )
) manifest["versionLatest"] = (
str(outdated.latest) if outdated.latest else None
)
result.append(manifest)
return True json_result[storage_dir] = result
return click.echo(
json.dumps(
json_result[storage_dirs[0]] if len(storage_dirs) == 1 else json_result
)
)
@cli.command("list", short_help="List installed libraries") @cli.command("list", short_help="List installed libraries")
@ -321,29 +284,18 @@ def lib_list(ctx, json_output):
"the next releases. \nPlease use `pio pkg list` instead.\n", "the next releases. \nPlease use `pio pkg list` instead.\n",
fg="yellow", fg="yellow",
) )
return invoke_command(ctx, package_list_cmd, only_libraries=True)
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY] storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY]
json_result = {} json_result = {}
for storage_dir in storage_dirs: for storage_dir in storage_dirs:
if not json_output:
print_storage_header(storage_dirs, storage_dir)
lm = LibraryPackageManager(storage_dir) lm = LibraryPackageManager(storage_dir)
items = lm.legacy_get_installed() json_result[storage_dir] = lm.legacy_get_installed()
if json_output: return click.echo(
json_result[storage_dir] = items json.dumps(
elif items: json_result[storage_dirs[0]] if len(storage_dirs) == 1 else json_result
for item in sorted(items, key=lambda i: i["name"]):
print_lib_item(item)
else:
click.echo("No items found")
if json_output:
return click.echo(
json.dumps(
json_result[storage_dirs[0]] if len(storage_dirs) == 1 else json_result
)
) )
)
return True
@cli.command("search", short_help="Search for a library") @cli.command("search", short_help="Search for a library")
@ -363,14 +315,10 @@ def lib_list(ctx, json_output):
is_flag=True, is_flag=True,
help="Do not prompt, automatically paginate with delay", help="Do not prompt, automatically paginate with delay",
) )
def lib_search(query, json_output, page, noninteractive, **filters): @click.pass_context
if not json_output: def lib_search( # pylint: disable=unused-argument
click.secho( ctx, query, json_output, page, noninteractive, **filters
"\nWARNING: This command is deprecated and will be removed in " ):
"the next releases. \nPlease use `pio pkg search` instead.\n",
fg="yellow",
)
regclient = LibraryPackageManager().get_registry_client_instance()
if not query: if not query:
query = [] query = []
if not isinstance(query, list): if not isinstance(query, list):
@ -380,72 +328,30 @@ def lib_search(query, json_output, page, noninteractive, **filters):
for value in values: for value in values:
query.append('%s:"%s"' % (key, value)) query.append('%s:"%s"' % (key, value))
if not json_output:
click.secho(
"\nWARNING: This command is deprecated and will be removed in "
"the next releases. \nPlease use `pio pkg search` instead.\n",
fg="yellow",
)
query.append("type:library")
return ctx.invoke(package_search_cmd, query=" ".join(query), page=page)
regclient = LibraryPackageManager().get_registry_client_instance()
result = regclient.fetch_json_data( result = regclient.fetch_json_data(
"get", "get",
"/v2/lib/search", "/v2/lib/search",
params=dict(query=" ".join(query), page=page), params=dict(query=" ".join(query), page=page),
x_cache_valid="1d", x_cache_valid="1d",
) )
return click.echo(json.dumps(result))
if json_output:
click.echo(json.dumps(result))
return
if result["total"] == 0:
click.secho(
"Nothing has been found by your request\n"
"Try a less-specific search or use truncation (or wildcard) "
"operator",
fg="yellow",
nl=False,
)
click.secho(" *", fg="green")
click.secho("For example: DS*, PCA*, DHT* and etc.\n", fg="yellow")
click.echo(
"For more examples and advanced search syntax, please use documentation:"
)
click.secho(
"https://docs.platformio.org/page/userguide/lib/cmd_search.html\n",
fg="cyan",
)
return
click.secho(
"Found %d libraries:\n" % result["total"],
fg="green" if result["total"] else "yellow",
)
while True:
for item in result["items"]:
print_lib_item(item)
if int(result["page"]) * int(result["perpage"]) >= int(result["total"]):
break
if noninteractive:
click.echo()
click.secho(
"Loading next %d libraries... Press Ctrl+C to stop!"
% result["perpage"],
fg="yellow",
)
click.echo()
time.sleep(5)
elif not click.confirm("Show next libraries?"):
break
result = regclient.fetch_json_data(
"get",
"/v2/lib/search",
params=dict(query=" ".join(query), page=int(result["page"]) + 1),
x_cache_valid="1d",
)
@cli.command("builtin", short_help="List built-in libraries") @cli.command("builtin", short_help="List built-in libraries")
@click.option("--storage", multiple=True) @click.option("--storage", multiple=True)
@click.option("--json-output", is_flag=True) @click.option("--json-output", is_flag=True)
def lib_builtin(storage, json_output): def lib_builtin(storage, json_output):
items = get_builtin_libs(storage) items = LibraryPackageManager.get_builtin_libs(storage)
if json_output: if json_output:
return click.echo(json.dumps(items)) return click.echo(json.dumps(items))
@ -465,13 +371,16 @@ def lib_builtin(storage, json_output):
@cli.command("show", short_help="Show detailed info about a library") @cli.command("show", short_help="Show detailed info about a library")
@click.argument("library", metavar="[LIBRARY]") @click.argument("library", metavar="[LIBRARY]")
@click.option("--json-output", is_flag=True) @click.option("--json-output", is_flag=True)
def lib_show(library, json_output): @click.pass_context
def lib_show(ctx, library, json_output):
if not json_output: if not json_output:
click.secho( click.secho(
"\nWARNING: This command is deprecated and will be removed in " "\nWARNING: This command is deprecated and will be removed in "
"the next releases. \nPlease use `pio pkg show` instead.\n", "the next releases. \nPlease use `pio pkg show` instead.\n",
fg="yellow", fg="yellow",
) )
return ctx.invoke(package_show_cmd, pkg_type="library", spec=library)
lm = LibraryPackageManager() lm = LibraryPackageManager()
lm.set_log_level(logging.ERROR if json_output else logging.DEBUG) lm.set_log_level(logging.ERROR if json_output else logging.DEBUG)
lib_id = lm.reveal_registry_package_id(library) lib_id = lm.reveal_registry_package_id(library)
@ -479,86 +388,7 @@ def lib_show(library, json_output):
lib = regclient.fetch_json_data( lib = regclient.fetch_json_data(
"get", "/v2/lib/info/%d" % lib_id, x_cache_valid="1h" "get", "/v2/lib/info/%d" % lib_id, x_cache_valid="1h"
) )
if json_output: return click.echo(json.dumps(lib))
return click.echo(json.dumps(lib))
title = "{ownername}/{name}".format(**lib)
click.secho(title, fg="cyan")
click.echo("=" * len(title))
click.echo(lib["description"])
click.echo()
click.secho("ID: %d" % lib["id"])
click.echo(
"Version: %s, released %s"
% (
lib["version"]["name"],
util.parse_datetime(lib["version"]["released"]).strftime("%c"),
)
)
click.echo("Manifest: %s" % lib["confurl"])
for key in ("homepage", "repository", "license"):
if key not in lib or not lib[key]:
continue
if isinstance(lib[key], list):
click.echo("%s: %s" % (key.capitalize(), ", ".join(lib[key])))
else:
click.echo("%s: %s" % (key.capitalize(), lib[key]))
blocks = []
_authors = []
for author in lib.get("authors", []):
_data = []
for key in ("name", "email", "url", "maintainer"):
if not author.get(key):
continue
if key == "email":
_data.append("<%s>" % author[key])
elif key == "maintainer":
_data.append("(maintainer)")
else:
_data.append(author[key])
_authors.append(" ".join(_data))
if _authors:
blocks.append(("Authors", _authors))
blocks.append(("Keywords", lib["keywords"]))
for key in ("frameworks", "platforms"):
if key not in lib or not lib[key]:
continue
blocks.append(("Compatible %s" % key, [i["title"] for i in lib[key]]))
blocks.append(("Headers", lib["headers"]))
blocks.append(("Examples", lib["examples"]))
blocks.append(
(
"Versions",
[
"%s, released %s"
% (v["name"], util.parse_datetime(v["released"]).strftime("%c"))
for v in lib["versions"]
],
)
)
blocks.append(
(
"Unique Downloads",
[
"Today: %s" % lib["dlstats"]["day"],
"Week: %s" % lib["dlstats"]["week"],
"Month: %s" % lib["dlstats"]["month"],
],
)
)
for (title, rows) in blocks:
click.echo()
click.secho(title, bold=True)
click.echo("-" * len(title))
for row in rows:
click.echo(row)
return True
@cli.command("register", short_help="Deprecated") @cli.command("register", short_help="Deprecated")
@ -572,76 +402,18 @@ def lib_register(config_url): # pylint: disable=unused-argument
@cli.command("stats", short_help="Library Registry Statistics") @cli.command("stats", short_help="Library Registry Statistics")
@click.option("--json-output", is_flag=True) @click.option("--json-output", is_flag=True)
def lib_stats(json_output): def lib_stats(json_output):
if not json_output:
click.secho(
"\nWARNING: This command is deprecated and will be removed in "
"the next releases. \nPlease visit "
"https://registry.platformio.org\n",
fg="yellow",
)
return None
regclient = LibraryPackageManager().get_registry_client_instance() regclient = LibraryPackageManager().get_registry_client_instance()
result = regclient.fetch_json_data("get", "/v2/lib/stats", x_cache_valid="1h") result = regclient.fetch_json_data("get", "/v2/lib/stats", x_cache_valid="1h")
return click.echo(json.dumps(result))
if json_output:
return click.echo(json.dumps(result))
for key in ("updated", "added"):
tabular_data = [
(
click.style(item["name"], fg="cyan"),
util.parse_datetime(item["date"]).strftime("%c"),
"https://platformio.org/lib/show/%s/%s"
% (item["id"], quote(item["name"])),
)
for item in result.get(key, [])
]
table = tabulate(
tabular_data,
headers=[click.style("RECENTLY " + key.upper(), bold=True), "Date", "URL"],
)
click.echo(table)
click.echo()
for key in ("lastkeywords", "topkeywords"):
tabular_data = [
(
click.style(name, fg="cyan"),
"https://platformio.org/lib/search?query=" + quote("keyword:%s" % name),
)
for name in result.get(key, [])
]
table = tabulate(
tabular_data,
headers=[
click.style(
("RECENT" if key == "lastkeywords" else "POPULAR") + " KEYWORDS",
bold=True,
),
"URL",
],
)
click.echo(table)
click.echo()
for key, title in (("dlday", "Today"), ("dlweek", "Week"), ("dlmonth", "Month")):
tabular_data = [
(
click.style(item["name"], fg="cyan"),
"https://platformio.org/lib/show/%s/%s"
% (item["id"], quote(item["name"])),
)
for item in result.get(key, [])
]
table = tabulate(
tabular_data,
headers=[click.style("FEATURED: " + title.upper(), bold=True), "URL"],
)
click.echo(table)
click.echo()
return True
def print_storage_header(storage_dirs, storage_dir):
if storage_dirs and storage_dirs[0] != storage_dir:
click.echo("")
click.echo(
click.style("Library Storage: ", bold=True)
+ click.style(storage_dir, fg="blue")
)
def print_lib_item(item): def print_lib_item(item):

View File

@ -1,13 +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.

View File

@ -1,104 +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 os
from platformio import util
from platformio.compat import ci_strings_are_equal
from platformio.package.manager.platform import PlatformPackageManager
from platformio.package.meta import PackageSpec
from platformio.platform.factory import PlatformFactory
from platformio.project.config import ProjectConfig
from platformio.project.exception import InvalidProjectConfError
@util.memoized(expire="60s")
def get_builtin_libs(storage_names=None):
# pylint: disable=import-outside-toplevel
from platformio.package.manager.library import LibraryPackageManager
items = []
storage_names = storage_names or []
pm = PlatformPackageManager()
for pkg in pm.get_installed():
p = PlatformFactory.new(pkg)
for storage in p.get_lib_storages():
if storage_names and storage["name"] not in storage_names:
continue
lm = LibraryPackageManager(storage["path"])
items.append(
{
"name": storage["name"],
"path": storage["path"],
"items": lm.legacy_get_installed(),
}
)
return items
def is_builtin_lib(name):
for storage in get_builtin_libs():
for lib in storage["items"]:
if lib.get("name") == name:
return True
return False
def ignore_deps_by_specs(deps, specs):
result = []
for dep in deps:
depspec = PackageSpec(dep)
if depspec.external:
result.append(dep)
continue
ignore_conditions = []
for spec in specs:
if depspec.owner:
ignore_conditions.append(
ci_strings_are_equal(depspec.owner, spec.owner)
and ci_strings_are_equal(depspec.name, spec.name)
)
else:
ignore_conditions.append(ci_strings_are_equal(depspec.name, spec.name))
if not any(ignore_conditions):
result.append(dep)
return result
def save_project_libdeps(project_dir, specs, environments=None, action="add"):
config = ProjectConfig.get_instance(os.path.join(project_dir, "platformio.ini"))
config.validate(environments)
for env in config.envs():
if environments and env not in environments:
continue
config.expand_interpolations = False
candidates = []
try:
candidates = ignore_deps_by_specs(
config.get("env:" + env, "lib_deps"), specs
)
except InvalidProjectConfError:
pass
if action == "add":
candidates.extend(spec.as_dependency() for spec in specs)
if candidates:
result = []
for item in candidates:
item = item.strip()
if item and item not in result:
result.append(item)
config.set("env:" + env, "lib_deps", result)
elif config.has_option("env:" + env, "lib_deps"):
config.remove_option("env:" + env, "lib_deps")
config.save()

View File

@ -74,8 +74,8 @@ def platform_frameworks(query, json_output):
if not json_output: if not json_output:
click.secho( click.secho(
"\nWARNING: This command is deprecated and will be removed in " "\nWARNING: This command is deprecated and will be removed in "
"the next releases. \nPlease https://docs.platformio.org" "the next releases. \nPlease visit https://docs.platformio.org"
"/en/latest/frameworks/index.html.\n", "/en/latest/frameworks/index.html\n",
fg="yellow", fg="yellow",
) )
return return

View File

@ -129,7 +129,11 @@ def fetch_package_data(spec, pkg_type=None):
return client.get_package( return client.get_package(
pkg_type, spec.owner, spec.name, version=spec.requirements pkg_type, spec.owner, spec.name, version=spec.requirements
) )
qualifiers = dict(names=spec.name.lower()) qualifiers = {}
if spec.id:
qualifiers["ids"] = str(spec.id)
if spec.name:
qualifiers["names"] = spec.name.lower()
if pkg_type: if pkg_type:
qualifiers["types"] = pkg_type qualifiers["types"] = pkg_type
if spec.owner: if spec.owner:

View File

@ -15,10 +15,11 @@
import json import json
import os import os
from platformio.commands.lib.helpers import is_builtin_lib from platformio import util
from platformio.package.exception import MissingPackageManifestError from platformio.package.exception import MissingPackageManifestError
from platformio.package.manager.base import BasePackageManager from platformio.package.manager.base import BasePackageManager
from platformio.package.meta import PackageSpec, PackageType from platformio.package.meta import PackageSpec, PackageType
from platformio.platform.factory import PlatformFactory
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
@ -84,7 +85,39 @@ class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-anc
# skip built-in dependencies # skip built-in dependencies
not_builtin_conds = [spec.external, spec.owner] not_builtin_conds = [spec.external, spec.owner]
if not any(not_builtin_conds): if not any(not_builtin_conds):
not_builtin_conds.append(not is_builtin_lib(spec.name)) not_builtin_conds.append(not self.is_builtin_lib(spec.name))
if any(not_builtin_conds): if any(not_builtin_conds):
return super().install_dependency(dependency) return super().install_dependency(dependency)
return None return None
@staticmethod
@util.memoized(expire="60s")
def get_builtin_libs(storage_names=None):
# pylint: disable=import-outside-toplevel
from platformio.package.manager.platform import PlatformPackageManager
items = []
storage_names = storage_names or []
pm = PlatformPackageManager()
for pkg in pm.get_installed():
p = PlatformFactory.new(pkg)
for storage in p.get_lib_storages():
if storage_names and storage["name"] not in storage_names:
continue
lm = LibraryPackageManager(storage["path"])
items.append(
{
"name": storage["name"],
"path": storage["path"],
"items": lm.legacy_get_installed(),
}
)
return items
@classmethod
def is_builtin_lib(cls, name):
for storage in cls.get_builtin_libs():
for lib in storage["items"]:
if lib.get("name") == name:
return True
return False

View File

@ -15,7 +15,7 @@
from os.path import isfile, join from os.path import isfile, join
from platformio.commands.ci import cli as cmd_ci from platformio.commands.ci import cli as cmd_ci
from platformio.commands.lib.command import cli as cmd_lib from platformio.package.commands.install import package_install_cmd
def test_ci_empty(clirunner): def test_ci_empty(clirunner):
@ -170,7 +170,8 @@ def test_ci_project_conf(clirunner, validate_cliresult):
def test_ci_lib_and_board(clirunner, tmpdir_factory, validate_cliresult): def test_ci_lib_and_board(clirunner, tmpdir_factory, validate_cliresult):
storage_dir = str(tmpdir_factory.mktemp("lib")) storage_dir = str(tmpdir_factory.mktemp("lib"))
result = clirunner.invoke( result = clirunner.invoke(
cmd_lib, ["--storage-dir", storage_dir, "install", "1@2.3.2"] package_install_cmd,
["--global", "--storage-dir", storage_dir, "--library", "1"],
) )
validate_cliresult(result) validate_cliresult(result)
@ -182,7 +183,7 @@ def test_ci_lib_and_board(clirunner, tmpdir_factory, validate_cliresult):
"OneWire", "OneWire",
"examples", "examples",
"DS2408_Switch", "DS2408_Switch",
"DS2408_Switch.pde", "DS2408_Switch.ino",
), ),
"-l", "-l",
join(storage_dir, "OneWire"), join(storage_dir, "OneWire"),

View File

@ -20,7 +20,7 @@ import os
import pytest import pytest
import semantic_version import semantic_version
from platformio.commands.lib.command import cli as cmd_lib from platformio.commands.lib import cli as cmd_lib
from platformio.package.meta import PackageType from platformio.package.meta import PackageType
from platformio.package.vcsclient import VCSClientFactory from platformio.package.vcsclient import VCSClientFactory
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
@ -137,11 +137,7 @@ lib_deps =
# test list # test list
result = clirunner.invoke(cmd_lib, ["-d", str(project_dir), "list"]) result = clirunner.invoke(cmd_lib, ["-d", str(project_dir), "list"])
validate_cliresult(result) validate_cliresult(result)
assert "Version: 0.8.3+sha." in result.stdout assert "AsyncMqttClient-esphome @ 0.8.3+sha.f5aa899" in result.stdout
assert (
"Source: git+https://github.com/OttoWinter/async-mqtt-client.git#v0.8.3"
in result.stdout
)
result = clirunner.invoke( result = clirunner.invoke(
cmd_lib, ["-d", str(project_dir), "list", "--json-output"] cmd_lib, ["-d", str(project_dir), "list", "--json-output"]
) )

View File

@ -18,7 +18,7 @@ import json
import re import re
from platformio.cli import PlatformioCLI from platformio.cli import PlatformioCLI
from platformio.commands.lib.command import cli as cmd_lib from platformio.commands.lib import cli as cmd_lib
from platformio.package.exception import UnknownPackageError from platformio.package.exception import UnknownPackageError
from platformio.util import strip_ansi_codes from platformio.util import strip_ansi_codes
@ -28,12 +28,12 @@ PlatformioCLI.leftover_args = ["--json-output"] # hook for click
def test_search(clirunner, validate_cliresult): def test_search(clirunner, validate_cliresult):
result = clirunner.invoke(cmd_lib, ["search", "DHT22"]) result = clirunner.invoke(cmd_lib, ["search", "DHT22"])
validate_cliresult(result) validate_cliresult(result)
match = re.search(r"Found\s+(\d+)\slibraries:", result.output) match = re.search(r"Found\s+(\d+)\spackages", result.output)
assert int(match.group(1)) > 2 assert int(match.group(1)) > 2
result = clirunner.invoke(cmd_lib, ["search", "DHT22", "--platform=timsp430"]) result = clirunner.invoke(cmd_lib, ["search", "DHT22", "--platform=timsp430"])
validate_cliresult(result) validate_cliresult(result)
match = re.search(r"Found\s+(\d+)\slibraries:", result.output) match = re.search(r"Found\s+(\d+)\spackages", result.output)
assert int(match.group(1)) > 1 assert int(match.group(1)) > 1
@ -175,10 +175,10 @@ def test_global_lib_list(clirunner, validate_cliresult):
assert all( assert all(
n in result.output n in result.output
for n in ( for n in (
"Source: https://github.com/Pedroalbuquerque/ESP32WebServer/archive/master.zip", "required: https://github.com/Pedroalbuquerque/ESP32WebServer/archive/master.zip",
"Version: 5.10.1", "ArduinoJson @ 5.10.1",
"Source: git+https://github.com/gioblu/PJON.git#3.0", "required: git+https://github.com/gioblu/PJON.git#3.0",
"Version: 3.0.0+sha.1fb26fd", "PJON @ 3.0.0+sha.1fb26f",
) )
) )
@ -251,11 +251,12 @@ def test_global_lib_update(clirunner, validate_cliresult):
validate_cliresult(result) validate_cliresult(result)
assert "Removing NeoPixelBus @ 2.2.4" in strip_ansi_codes(result.output) assert "Removing NeoPixelBus @ 2.2.4" in strip_ansi_codes(result.output)
# update rest libraries # update all libraries
result = clirunner.invoke(cmd_lib, ["-g", "update"]) result = clirunner.invoke(
cmd_lib,
["-g", "update", "adafruit/Adafruit PN532", "marvinroger/AsyncMqttClient"],
)
validate_cliresult(result) validate_cliresult(result)
assert result.output.count("+sha.") == 4
assert result.output.count("already up-to-date") == 14
# update unknown library # update unknown library
result = clirunner.invoke(cmd_lib, ["-g", "update", "Unknown"]) result = clirunner.invoke(cmd_lib, ["-g", "update", "Unknown"])
@ -314,7 +315,7 @@ def test_global_lib_uninstall(clirunner, validate_cliresult, isolated_pio_core):
def test_lib_show(clirunner, validate_cliresult): def test_lib_show(clirunner, validate_cliresult):
result = clirunner.invoke(cmd_lib, ["show", "64"]) result = clirunner.invoke(cmd_lib, ["show", "64"])
validate_cliresult(result) validate_cliresult(result)
assert all(s in result.output for s in ("ArduinoJson", "Arduino", "Atmel AVR")) assert all(s in result.output for s in ("ArduinoJson", "Arduino"))
result = clirunner.invoke(cmd_lib, ["show", "OneWire", "--json-output"]) result = clirunner.invoke(cmd_lib, ["show", "OneWire", "--json-output"])
validate_cliresult(result) validate_cliresult(result)
assert "OneWire" in result.output assert "OneWire" in result.output
@ -328,13 +329,6 @@ def test_lib_builtin(clirunner, validate_cliresult):
def test_lib_stats(clirunner, validate_cliresult): def test_lib_stats(clirunner, validate_cliresult):
result = clirunner.invoke(cmd_lib, ["stats"])
validate_cliresult(result)
assert all(
s in result.output
for s in ("UPDATED", "POPULAR", "https://platformio.org/lib/show")
)
result = clirunner.invoke(cmd_lib, ["stats", "--json-output"]) result = clirunner.invoke(cmd_lib, ["stats", "--json-output"])
validate_cliresult(result) validate_cliresult(result)
assert set( assert set(