Merge branch 'release/v5.0.1'

This commit is contained in:
Ivan Kravets
2020-09-10 17:46:56 +03:00
38 changed files with 432 additions and 148 deletions

View File

@ -8,11 +8,23 @@ PlatformIO Core 5
**A professional collaborative platform for embedded development** **A professional collaborative platform for embedded development**
- `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/core/migration.html>`__ 5.0.1 (2020-09-10)
~~~~~~~~~~~~~~~~~~
- Added support for "owner" requirement when declaring ``dependencies`` using `library.json <https://docs.platformio.org/page/librarymanager/config.html#dependencies>`__
- Fixed an issue when using a custom git/ssh package with `platform_packages <https://docs.platformio.org/page/projectconf/section_env_platform.html#platform-packages>`__ option (`issue #3624 <https://github.com/platformio/platformio-core/issues/3624>`_)
- Fixed an issue with "ImportError: cannot import name '_get_backend' from 'cryptography.hazmat.backends'" when using `Remote Development <https://docs.platformio.org/page/plus/pio-remote.html>`__ on RaspberryPi device (`issue #3652 <https://github.com/platformio/platformio-core/issues/3652>`_)
- Fixed an issue when `pio package unpublish <https://docs.platformio.org/page/core/userguide/package/cmd_unpublish.html>`__ command crashes (`issue #3660 <https://github.com/platformio/platformio-core/issues/3660>`_)
- Fixed an issue when the package manager tries to install a built-in library from the registry (`issue #3662 <https://github.com/platformio/platformio-core/issues/3662>`_)
- Fixed an issue with incorrect value for C++ language standard in IDE projects when an in-progress language standard is used (`issue #3653 <https://github.com/platformio/platformio-core/issues/3653>`_)
- Fixed an issue with "Invalid simple block (semantic_version)" from library dependency that refs to an external source (repository, ZIP/Tar archives) (`issue #3658 <https://github.com/platformio/platformio-core/issues/3658>`_)
- Fixed an issue when can not remove update or remove external dev-platform using PlatformIO Home (`issue #3663 <https://github.com/platformio/platformio-core/issues/3663>`_)
5.0.0 (2020-09-03) 5.0.0 (2020-09-03)
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
Please check `Migration guide from 4.x to 5.0 <https://docs.platformio.org/page/core/migration.html>`__.
* Integration with the new **PlatformIO Trusted Registry** * Integration with the new **PlatformIO Trusted Registry**
- Enterprise-grade package storage with high availability (multi replicas) - Enterprise-grade package storage with high availability (multi replicas)

2
docs

Submodule docs updated: 03a83c996f...9bbb02295a

View File

@ -14,7 +14,7 @@
import sys import sys
VERSION = (5, 0, 0) VERSION = (5, 0, 1)
__version__ = ".".join([str(s) for s in VERSION]) __version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio" __title__ = "platformio"

View File

@ -80,7 +80,9 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
) )
data = self.fetch_json_data( data = self.fetch_json_data(
"post", "/v1/login", data={"username": username, "password": password}, "post",
"/v1/login",
data={"username": username, "password": password},
) )
app.set_state_item("account", data) app.set_state_item("account", data)
return data return data
@ -108,7 +110,9 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
self.delete_local_session() self.delete_local_session()
try: try:
self.fetch_json_data( self.fetch_json_data(
"post", "/v1/logout", data={"refresh_token": refresh_token}, "post",
"/v1/logout",
data={"refresh_token": refresh_token},
) )
except AccountError: except AccountError:
pass pass
@ -153,15 +157,26 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
).get("auth_token") ).get("auth_token")
def forgot_password(self, username): def forgot_password(self, username):
return self.fetch_json_data("post", "/v1/forgot", data={"username": username},) return self.fetch_json_data(
"post",
"/v1/forgot",
data={"username": username},
)
def get_profile(self): def get_profile(self):
return self.send_auth_request("get", "/v1/profile",) return self.send_auth_request(
"get",
"/v1/profile",
)
def update_profile(self, profile, current_password): def update_profile(self, profile, current_password):
profile["current_password"] = current_password profile["current_password"] = current_password
self.delete_local_state("summary") self.delete_local_state("summary")
response = self.send_auth_request("put", "/v1/profile", data=profile,) response = self.send_auth_request(
"put",
"/v1/profile",
data=profile,
)
return response return response
def get_account_info(self, offline=False): def get_account_info(self, offline=False):
@ -178,7 +193,10 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
"username": account.get("username"), "username": account.get("username"),
} }
} }
result = self.send_auth_request("get", "/v1/summary",) result = self.send_auth_request(
"get",
"/v1/summary",
)
account["summary"] = dict( account["summary"] = dict(
profile=result.get("profile"), profile=result.get("profile"),
packages=result.get("packages"), packages=result.get("packages"),
@ -203,7 +221,10 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
return self.send_auth_request("get", "/v1/orgs/%s" % orgname) return self.send_auth_request("get", "/v1/orgs/%s" % orgname)
def list_orgs(self): def list_orgs(self):
return self.send_auth_request("get", "/v1/orgs",) return self.send_auth_request(
"get",
"/v1/orgs",
)
def update_org(self, orgname, data): def update_org(self, orgname, data):
return self.send_auth_request( return self.send_auth_request(
@ -211,19 +232,29 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
) )
def destroy_org(self, orgname): def destroy_org(self, orgname):
return self.send_auth_request("delete", "/v1/orgs/%s" % orgname,) return self.send_auth_request(
"delete",
"/v1/orgs/%s" % orgname,
)
def add_org_owner(self, orgname, username): def add_org_owner(self, orgname, username):
return self.send_auth_request( return self.send_auth_request(
"post", "/v1/orgs/%s/owners" % orgname, data={"username": username}, "post",
"/v1/orgs/%s/owners" % orgname,
data={"username": username},
) )
def list_org_owners(self, orgname): def list_org_owners(self, orgname):
return self.send_auth_request("get", "/v1/orgs/%s/owners" % orgname,) return self.send_auth_request(
"get",
"/v1/orgs/%s/owners" % orgname,
)
def remove_org_owner(self, orgname, username): def remove_org_owner(self, orgname, username):
return self.send_auth_request( return self.send_auth_request(
"delete", "/v1/orgs/%s/owners" % orgname, data={"username": username}, "delete",
"/v1/orgs/%s/owners" % orgname,
data={"username": username},
) )
def create_team(self, orgname, teamname, description): def create_team(self, orgname, teamname, description):
@ -235,16 +266,21 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
def destroy_team(self, orgname, teamname): def destroy_team(self, orgname, teamname):
return self.send_auth_request( return self.send_auth_request(
"delete", "/v1/orgs/%s/teams/%s" % (orgname, teamname), "delete",
"/v1/orgs/%s/teams/%s" % (orgname, teamname),
) )
def get_team(self, orgname, teamname): def get_team(self, orgname, teamname):
return self.send_auth_request( return self.send_auth_request(
"get", "/v1/orgs/%s/teams/%s" % (orgname, teamname), "get",
"/v1/orgs/%s/teams/%s" % (orgname, teamname),
) )
def list_teams(self, orgname): def list_teams(self, orgname):
return self.send_auth_request("get", "/v1/orgs/%s/teams" % orgname,) return self.send_auth_request(
"get",
"/v1/orgs/%s/teams" % orgname,
)
def update_team(self, orgname, teamname, data): def update_team(self, orgname, teamname, data):
return self.send_auth_request( return self.send_auth_request(

View File

@ -70,12 +70,16 @@ class RegistryClient(HTTPClient):
if version: if version:
path += "/" + version path += "/" + version
return self.send_auth_request( return self.send_auth_request(
"delete", path, params={"undo": 1 if undo else 0}, "delete",
path,
params={"undo": 1 if undo else 0},
) )
def update_resource(self, urn, private): def update_resource(self, urn, private):
return self.send_auth_request( return self.send_auth_request(
"put", "/v3/resources/%s" % urn, data={"private": int(private)}, "put",
"/v3/resources/%s" % urn,
data={"private": int(private)},
) )
def grant_access_for_resource(self, urn, client, level): def grant_access_for_resource(self, urn, client, level):
@ -87,7 +91,9 @@ class RegistryClient(HTTPClient):
def revoke_access_from_resource(self, urn, client): def revoke_access_from_resource(self, urn, client):
return self.send_auth_request( return self.send_auth_request(
"delete", "/v3/resources/%s/access" % urn, data={"client": client}, "delete",
"/v3/resources/%s/access" % urn,
data={"client": client},
) )
def list_resources(self, owner): def list_resources(self, owner):

View File

@ -47,27 +47,31 @@ def validate_urn(value):
@cli.command("public", short_help="Make resource public") @cli.command("public", short_help="Make resource public")
@click.argument( @click.argument(
"urn", callback=lambda _, __, value: validate_urn(value), "urn",
callback=lambda _, __, value: validate_urn(value),
) )
@click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg") @click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg")
def access_public(urn, urn_type): def access_public(urn, urn_type):
client = RegistryClient() client = RegistryClient()
client.update_resource(urn=urn, private=0) client.update_resource(urn=urn, private=0)
return click.secho( return click.secho(
"The resource %s has been successfully updated." % urn, fg="green", "The resource %s has been successfully updated." % urn,
fg="green",
) )
@cli.command("private", short_help="Make resource private") @cli.command("private", short_help="Make resource private")
@click.argument( @click.argument(
"urn", callback=lambda _, __, value: validate_urn(value), "urn",
callback=lambda _, __, value: validate_urn(value),
) )
@click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg") @click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg")
def access_private(urn, urn_type): def access_private(urn, urn_type):
client = RegistryClient() client = RegistryClient()
client.update_resource(urn=urn, private=1) client.update_resource(urn=urn, private=1)
return click.secho( return click.secho(
"The resource %s has been successfully updated." % urn, fg="green", "The resource %s has been successfully updated." % urn,
fg="green",
) )
@ -79,14 +83,16 @@ def access_private(urn, urn_type):
callback=lambda _, __, value: validate_client(value), callback=lambda _, __, value: validate_client(value),
) )
@click.argument( @click.argument(
"urn", callback=lambda _, __, value: validate_urn(value), "urn",
callback=lambda _, __, value: validate_urn(value),
) )
@click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg") @click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg")
def access_grant(level, client, urn, urn_type): def access_grant(level, client, urn, urn_type):
reg_client = RegistryClient() reg_client = RegistryClient()
reg_client.grant_access_for_resource(urn=urn, client=client, level=level) reg_client.grant_access_for_resource(urn=urn, client=client, level=level)
return click.secho( return click.secho(
"Access for resource %s has been granted for %s" % (urn, client), fg="green", "Access for resource %s has been granted for %s" % (urn, client),
fg="green",
) )
@ -97,14 +103,16 @@ def access_grant(level, client, urn, urn_type):
callback=lambda _, __, value: validate_client(value), callback=lambda _, __, value: validate_client(value),
) )
@click.argument( @click.argument(
"urn", callback=lambda _, __, value: validate_urn(value), "urn",
callback=lambda _, __, value: validate_urn(value),
) )
@click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg") @click.option("--urn-type", type=click.Choice(["prn:reg:pkg"]), default="prn:reg:pkg")
def access_revoke(client, urn, urn_type): def access_revoke(client, urn, urn_type):
reg_client = RegistryClient() reg_client = RegistryClient()
reg_client.revoke_access_from_resource(urn=urn, client=client) reg_client.revoke_access_from_resource(urn=urn, client=client)
return click.secho( return click.secho(
"Access for resource %s has been revoked for %s" % (urn, client), fg="green", "Access for resource %s has been revoked for %s" % (urn, client),
fg="green",
) )

View File

@ -192,7 +192,10 @@ def account_destroy():
client.logout() client.logout()
except AccountNotAuthorized: except AccountNotAuthorized:
pass pass
return click.secho("User account has been destroyed.", fg="green",) return click.secho(
"User account has been destroyed.",
fg="green",
)
@cli.command("show", short_help="PlatformIO Account information") @cli.command("show", short_help="PlatformIO Account information")

View File

@ -203,7 +203,9 @@ def device_monitor(**kwargs): # pylint: disable=too-many-branches
kwargs["port"] = ports[0]["port"] kwargs["port"] = ports[0]["port"]
elif "platform" in project_options and "board" in project_options: elif "platform" in project_options and "board" in project_options:
board_hwids = device_helpers.get_board_hwids( board_hwids = device_helpers.get_board_hwids(
kwargs["project_dir"], platform, project_options["board"], kwargs["project_dir"],
platform,
project_options["board"],
) )
for item in ports: for item in ports:
for hwid in board_hwids: for hwid in board_hwids:

View File

@ -22,11 +22,7 @@ from tabulate import tabulate
from platformio import exception, fs, util from platformio import exception, fs, util
from platformio.commands import PlatformioCLI from platformio.commands import PlatformioCLI
from platformio.commands.lib.helpers import ( from platformio.commands.lib.helpers import get_builtin_libs, save_project_libdeps
get_builtin_libs,
is_builtin_lib,
save_project_libdeps,
)
from platformio.compat import dump_json_to_unicode from platformio.compat import dump_json_to_unicode
from platformio.package.exception import NotGlobalLibDir, UnknownPackageError from platformio.package.exception import NotGlobalLibDir, UnknownPackageError
from platformio.package.manager.library import LibraryPackageManager from platformio.package.manager.library import LibraryPackageManager
@ -164,15 +160,8 @@ def lib_install( # pylint: disable=too-many-arguments,unused-argument
} }
elif storage_dir in storage_libdeps: elif storage_dir in storage_libdeps:
builtin_lib_storages = None
for library in storage_libdeps[storage_dir]: for library in storage_libdeps[storage_dir]:
try: lm.install(library, silent=silent, force=force)
lm.install(library, silent=silent, force=force)
except UnknownPackageError as e:
if builtin_lib_storages is None:
builtin_lib_storages = get_builtin_libs()
if not silent or not is_builtin_lib(builtin_lib_storages, library):
click.secho("Warning! %s" % e, fg="yellow")
if save and installed_pkgs: if save and installed_pkgs:
_save_deps(ctx, installed_pkgs) _save_deps(ctx, installed_pkgs)

View File

@ -45,10 +45,11 @@ def get_builtin_libs(storage_names=None):
return items return items
def is_builtin_lib(storages, name): def is_builtin_lib(name, storages=None):
for storage in storages or []: for storage in storages or get_builtin_libs():
if any(lib.get("name") == name for lib in storage["items"]): for lib in storage["items"]:
return True if lib.get("name") == name:
return True
return False return False

View File

@ -34,17 +34,21 @@ def validate_orgname(value):
@cli.command("create", short_help="Create a new organization") @cli.command("create", short_help="Create a new organization")
@click.argument( @click.argument(
"orgname", callback=lambda _, __, value: validate_orgname(value), "orgname",
callback=lambda _, __, value: validate_orgname(value),
) )
@click.option( @click.option(
"--email", callback=lambda _, __, value: validate_email(value) if value else value "--email", callback=lambda _, __, value: validate_email(value) if value else value
) )
@click.option("--displayname",) @click.option(
"--displayname",
)
def org_create(orgname, email, displayname): def org_create(orgname, email, displayname):
client = AccountClient() client = AccountClient()
client.create_org(orgname, email, displayname) client.create_org(orgname, email, displayname)
return click.secho( return click.secho(
"The organization `%s` has been successfully created." % orgname, fg="green", "The organization `%s` has been successfully created." % orgname,
fg="green",
) )
@ -121,12 +125,19 @@ def account_destroy(orgname):
abort=True, abort=True,
) )
client.destroy_org(orgname) client.destroy_org(orgname)
return click.secho("Organization `%s` has been destroyed." % orgname, fg="green",) return click.secho(
"Organization `%s` has been destroyed." % orgname,
fg="green",
)
@cli.command("add", short_help="Add a new owner to organization") @cli.command("add", short_help="Add a new owner to organization")
@click.argument("orgname",) @click.argument(
@click.argument("username",) "orgname",
)
@click.argument(
"username",
)
def org_add_owner(orgname, username): def org_add_owner(orgname, username):
client = AccountClient() client = AccountClient()
client.add_org_owner(orgname, username) client.add_org_owner(orgname, username)
@ -138,8 +149,12 @@ def org_add_owner(orgname, username):
@cli.command("remove", short_help="Remove an owner from organization") @cli.command("remove", short_help="Remove an owner from organization")
@click.argument("orgname",) @click.argument(
@click.argument("username",) "orgname",
)
@click.argument(
"username",
)
def org_remove_owner(orgname, username): def org_remove_owner(orgname, username):
client = AccountClient() client = AccountClient()
client.remove_org_owner(orgname, username) client.remove_org_owner(orgname, username)

View File

@ -107,7 +107,7 @@ def package_unpublish(package, type, undo): # pylint: disable=redefined-builtin
type=type, type=type,
name=spec.name, name=spec.name,
owner=spec.owner, owner=spec.owner,
version=spec.requirements, version=str(spec.requirements),
undo=undo, undo=undo,
) )
click.secho(response.get("message"), fg="green") click.secho(response.get("message"), fg="green")

View File

@ -45,7 +45,10 @@ class RemoteClientFactory(pb.PBClientFactory, protocol.ReconnectingClientFactory
return d return d
d = self.login( d = self.login(
credentials.UsernamePassword(auth_token.encode(), get_host_id().encode(),), credentials.UsernamePassword(
auth_token.encode(),
get_host_id().encode(),
),
client=self.remote_client, client=self.remote_client,
) )
d.addCallback(self.remote_client.cb_client_authorization_made) d.addCallback(self.remote_client.cb_client_authorization_made)

View File

@ -63,13 +63,16 @@ def cli():
value, teamname_validate=True value, teamname_validate=True
), ),
) )
@click.option("--description",) @click.option(
"--description",
)
def team_create(orgname_teamname, description): def team_create(orgname_teamname, description):
orgname, teamname = orgname_teamname.split(":", 1) orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient() client = AccountClient()
client.create_team(orgname, teamname, description) client.create_team(orgname, teamname, description)
return click.secho( return click.secho(
"The team %s has been successfully created." % teamname, fg="green", "The team %s has been successfully created." % teamname,
fg="green",
) )
@ -123,7 +126,9 @@ def team_list(orgname, json_output):
callback=lambda _, __, value: validate_teamname(value), callback=lambda _, __, value: validate_teamname(value),
help="A new team name", help="A new team name",
) )
@click.option("--description",) @click.option(
"--description",
)
def team_update(orgname_teamname, **kwargs): def team_update(orgname_teamname, **kwargs):
orgname, teamname = orgname_teamname.split(":", 1) orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient() client = AccountClient()
@ -142,7 +147,8 @@ def team_update(orgname_teamname, **kwargs):
new_team.update({key: value for key, value in kwargs.items() if value}) new_team.update({key: value for key, value in kwargs.items() if value})
client.update_team(orgname, teamname, new_team) client.update_team(orgname, teamname, new_team)
return click.secho( return click.secho(
"The team %s has been successfully updated." % teamname, fg="green", "The team %s has been successfully updated." % teamname,
fg="green",
) )
@ -163,7 +169,8 @@ def team_destroy(orgname_teamname):
client = AccountClient() client = AccountClient()
client.destroy_team(orgname, teamname) client.destroy_team(orgname, teamname)
return click.secho( return click.secho(
"The team %s has been successfully destroyed." % teamname, fg="green", "The team %s has been successfully destroyed." % teamname,
fg="green",
) )
@ -173,7 +180,9 @@ def team_destroy(orgname_teamname):
metavar="ORGNAME:TEAMNAME", metavar="ORGNAME:TEAMNAME",
callback=lambda _, __, value: validate_orgname_teamname(value), callback=lambda _, __, value: validate_orgname_teamname(value),
) )
@click.argument("username",) @click.argument(
"username",
)
def team_add_member(orgname_teamname, username): def team_add_member(orgname_teamname, username):
orgname, teamname = orgname_teamname.split(":", 1) orgname, teamname = orgname_teamname.split(":", 1)
client = AccountClient() client = AccountClient()

View File

@ -63,7 +63,7 @@ SET(CMAKE_CXX_COMPILER "{{ _normalize_path(cxx_path) }}")
SET(CMAKE_CXX_FLAGS "{{ _normalize_path(to_unix_path(cxx_flags)) }}") SET(CMAKE_CXX_FLAGS "{{ _normalize_path(to_unix_path(cxx_flags)) }}")
SET(CMAKE_C_FLAGS "{{ _normalize_path(to_unix_path(cc_flags)) }}") SET(CMAKE_C_FLAGS "{{ _normalize_path(to_unix_path(cc_flags)) }}")
% STD_RE = re.compile(r"\-std=[a-z\+]+(\d+)") % STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)")
% cc_stds = STD_RE.findall(cc_flags) % cc_stds = STD_RE.findall(cc_flags)
% cxx_stds = STD_RE.findall(cxx_flags) % cxx_stds = STD_RE.findall(cxx_flags)
% if cc_stds: % if cc_stds:

View File

@ -1,5 +1,5 @@
% import re % import re
% STD_RE = re.compile(r"(\-std=[a-z\+]+\d+)") % STD_RE = re.compile(r"(\-std=[a-z\+]+\w+)")
% cxx_stds = STD_RE.findall(cxx_flags) % cxx_stds = STD_RE.findall(cxx_flags)
% cxx_std = cxx_stds[-1] if cxx_stds else "" % cxx_std = cxx_stds[-1] if cxx_stds else ""
% %

View File

@ -1,5 +1,5 @@
% import re % import re
% STD_RE = re.compile(r"\-std=[a-z\+]+(\d+)") % STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)")
% cc_stds = STD_RE.findall(cc_flags) % cc_stds = STD_RE.findall(cc_flags)
% cxx_stds = STD_RE.findall(cxx_flags) % cxx_stds = STD_RE.findall(cxx_flags)
% %

View File

@ -1,5 +1,5 @@
% import re % import re
% STD_RE = re.compile(r"\-std=[a-z\+]+(\d+)") % STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)")
% cc_stds = STD_RE.findall(cc_flags) % cc_stds = STD_RE.findall(cc_flags)
% cxx_stds = STD_RE.findall(cxx_flags) % cxx_stds = STD_RE.findall(cxx_flags)
% %

View File

@ -6,6 +6,14 @@
% %
% systype = platform.system().lower() % systype = platform.system().lower()
% %
% cpp_standards_remap = {
% "0x": "11",
% "1y": "14",
% "1z": "17",
% "2a": "20",
% "2b": "23"
% }
%
% def _escape(text): % def _escape(text):
% return to_unix_path(text).replace('"', '\\"') % return to_unix_path(text).replace('"', '\\"')
% end % end
@ -68,7 +76,7 @@
% %
% cleaned_includes = filter_includes(includes, ["toolchain"]) % cleaned_includes = filter_includes(includes, ["toolchain"])
% %
% STD_RE = re.compile(r"\-std=[a-z\+]+(\d+)") % STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)")
% cc_stds = STD_RE.findall(cc_flags) % cc_stds = STD_RE.findall(cc_flags)
% cxx_stds = STD_RE.findall(cxx_flags) % cxx_stds = STD_RE.findall(cxx_flags)
% cc_m_flags = split_args(cc_flags) % cc_m_flags = split_args(cc_flags)
@ -115,7 +123,7 @@
"cStandard": "c{{ cc_stds[-1] }}", "cStandard": "c{{ cc_stds[-1] }}",
% end % end
% if cxx_stds: % if cxx_stds:
"cppStandard": "c++{{ cxx_stds[-1] }}", "cppStandard": "c++{{ cpp_standards_remap.get(cxx_stds[-1], cxx_stds[-1]) }}",
% end % end
% if forced_includes: % if forced_includes:
"forcedInclude": [ "forcedInclude": [

View File

@ -124,7 +124,9 @@ class Upgrader(object):
continue continue
result = result[0] result = result[0]
pkg.metadata.spec = PackageSpec( pkg.metadata.spec = PackageSpec(
id=result["id"], owner=result["owner"]["username"], name=result["name"], id=result["id"],
owner=result["owner"]["username"],
name=result["name"],
) )
pkg.dump_meta() pkg.dump_meta()
return True return True

View File

@ -91,7 +91,10 @@ class BasePackageManager( # pylint: disable=too-many-public-methods
@staticmethod @staticmethod
def ensure_dir_exists(path): def ensure_dir_exists(path):
if not os.path.isdir(path): if not os.path.isdir(path):
os.makedirs(path) try:
os.makedirs(path)
except: # pylint: disable=bare-except
pass
assert os.path.isdir(path) assert os.path.isdir(path)
return path return path

View File

@ -16,11 +16,12 @@ import json
import os import os
import subprocess import subprocess
import sys import sys
from datetime import date
from platformio import __core_packages__, exception, fs, util from platformio import __core_packages__, exception, fs, util
from platformio.compat import PY2 from platformio.compat import PY2
from platformio.package.manager.tool import ToolPackageManager from platformio.package.manager.tool import ToolPackageManager
from platformio.package.meta import PackageSpec from platformio.package.meta import PackageItem, PackageSpec
from platformio.proc import get_pythonexe_path from platformio.proc import get_pythonexe_path
@ -95,16 +96,8 @@ def build_contrib_pysite_deps(target_dir):
if os.path.isdir(target_dir): if os.path.isdir(target_dir):
fs.rmtree(target_dir) fs.rmtree(target_dir)
os.makedirs(target_dir) os.makedirs(target_dir)
with open(os.path.join(target_dir, "package.json"), "w") as fp:
json.dump(
dict(
name="contrib-pysite",
version="2.%d%d.0" % (sys.version_info.major, sys.version_info.minor),
system=util.get_systype(),
),
fp,
)
# build dependencies
pythonexe = get_pythonexe_path() pythonexe = get_pythonexe_path()
for dep in get_contrib_pysite_deps(): for dep in get_contrib_pysite_deps():
subprocess.check_call( subprocess.check_call(
@ -115,11 +108,36 @@ def build_contrib_pysite_deps(target_dir):
"install", "install",
# "--no-cache-dir", # "--no-cache-dir",
"--no-compile", "--no-compile",
"--no-binary",
":all:",
"-t", "-t",
target_dir, target_dir,
dep, dep,
] ]
) )
# build manifests
with open(os.path.join(target_dir, "package.json"), "w") as fp:
json.dump(
dict(
name="contrib-pysite",
version="2.%d%d.%s"
% (
sys.version_info.major,
sys.version_info.minor,
date.today().strftime("%y%m%d"),
),
system=util.get_systype(),
),
fp,
)
pm = ToolPackageManager()
pkg = PackageItem(target_dir)
pkg.metadata = pm.build_metadata(
target_dir, PackageSpec(owner="platformio", name="contrib-pysite")
)
pkg.dump_meta()
return True return True
@ -130,7 +148,7 @@ def get_contrib_pysite_deps():
twisted_version = "19.10.0" if PY2 else "20.3.0" twisted_version = "19.10.0" if PY2 else "20.3.0"
result = [ result = [
"twisted == %s" % twisted_version, "twisted == %s" % twisted_version,
"autobahn == 20.4.3", "autobahn == %s" % ("19.11.2" if PY2 else "20.4.3"),
"json-rpc == 1.13.0", "json-rpc == 1.13.0",
] ]

View File

@ -15,7 +15,10 @@
import json import json
import os import os
from platformio.package.exception import MissingPackageManifestError from platformio.package.exception import (
MissingPackageManifestError,
UnknownPackageError,
)
from platformio.package.manager.base import BasePackageManager from platformio.package.manager.base import BasePackageManager
from platformio.package.meta import PackageItem, PackageSpec, PackageType from platformio.package.meta import PackageItem, PackageSpec, PackageType
from platformio.project.helpers import get_project_global_lib_dir from platformio.project.helpers import get_project_global_lib_dir
@ -43,7 +46,10 @@ class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-anc
# automatically generate library manifest # automatically generate library manifest
with open(os.path.join(root_dir, "library.json"), "w") as fp: with open(os.path.join(root_dir, "library.json"), "w") as fp:
json.dump( json.dump(
dict(name=spec.name, version=self.generate_rand_version(),), dict(
name=spec.name,
version=self.generate_rand_version(),
),
fp, fp,
indent=2, indent=2,
) )
@ -63,6 +69,33 @@ class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-anc
return root return root
return path return path
def _install( # pylint: disable=too-many-arguments
self,
spec,
search_filters=None,
silent=False,
skip_dependencies=False,
force=False,
):
try:
return super(LibraryPackageManager, self)._install(
spec,
search_filters=search_filters,
silent=silent,
skip_dependencies=skip_dependencies,
force=force,
)
except UnknownPackageError as e:
# pylint: disable=import-outside-toplevel
from platformio.commands.lib.helpers import is_builtin_lib
spec = self.ensure_spec(spec)
if is_builtin_lib(spec.name):
self.print_message("Already installed, built-in library", fg="yellow")
return True
raise e
def install_dependencies(self, pkg, silent=False): def install_dependencies(self, pkg, silent=False):
assert isinstance(pkg, PackageItem) assert isinstance(pkg, PackageItem)
manifest = self.load_manifest(pkg) manifest = self.load_manifest(pkg)
@ -79,9 +112,16 @@ class LibraryPackageManager(BasePackageManager): # pylint: disable=too-many-anc
) )
def _install_dependency(self, dependency, silent=False): def _install_dependency(self, dependency, silent=False):
spec = PackageSpec( if set(["name", "version"]) <= set(dependency.keys()) and any(
name=dependency.get("name"), requirements=dependency.get("version") c in dependency["version"] for c in (":", "/", "@")
) ):
spec = PackageSpec("%s=%s" % (dependency["name"], dependency["version"]))
else:
spec = PackageSpec(
owner=dependency.get("owner"),
name=dependency.get("name"),
requirements=dependency.get("version"),
)
search_filters = { search_filters = {
key: value key: value
for key, value in dependency.items() for key, value in dependency.items()

View File

@ -388,7 +388,15 @@ class LibraryJsonManifestParser(BaseManifestParser):
raw = [raw] raw = [raw]
if isinstance(raw, dict): if isinstance(raw, dict):
return [dict(name=name, version=version) for name, version in raw.items()] result = []
for name, version in raw.items():
if "/" in name:
owner, name = name.split("/", 1)
result.append(dict(owner=owner, name=name, version=version))
else:
result.append(dict(name=name, version=version))
return result
if isinstance(raw, list): if isinstance(raw, list):
for i, dependency in enumerate(raw): for i, dependency in enumerate(raw):
if isinstance(dependency, dict): if isinstance(dependency, dict):

View File

@ -106,6 +106,7 @@ class RepositorySchema(StrictSchema):
class DependencySchema(StrictSchema): class DependencySchema(StrictSchema):
owner = fields.Str(validate=validate.Length(min=1, max=100))
name = fields.Str(required=True, validate=validate.Length(min=1, max=100)) name = fields.Str(required=True, validate=validate.Length(min=1, max=100))
version = fields.Str(validate=validate.Length(min=1, max=100)) version = fields.Str(validate=validate.Length(min=1, max=100))
authors = StrictListField(fields.Str(validate=validate.Length(min=1, max=50))) authors = StrictListField(fields.Str(validate=validate.Length(min=1, max=50)))
@ -242,7 +243,7 @@ class ManifestSchema(BaseSchema):
raise ValidationError("Could not load SPDX licenses for validation") raise ValidationError("Could not load SPDX licenses for validation")
for item in spdx.get("licenses", []): for item in spdx.get("licenses", []):
if item.get("licenseId") == value: if item.get("licenseId") == value:
return return True
raise ValidationError( raise ValidationError(
"Invalid SPDX license identifier. See valid identifiers at " "Invalid SPDX license identifier. See valid identifiers at "
"https://spdx.org/licenses/" "https://spdx.org/licenses/"
@ -251,9 +252,5 @@ class ManifestSchema(BaseSchema):
@staticmethod @staticmethod
@memoized(expire="1h") @memoized(expire="1h")
def load_spdx_licenses(): def load_spdx_licenses():
version = "3.10" spdx_data_url = "https://dl.bintray.com/platformio/dl-misc/spdx-licenses-3.json"
spdx_data_url = (
"https://raw.githubusercontent.com/spdx/license-list-data"
"/v%s/json/licenses.json" % version
)
return json.loads(fetch_remote_content(spdx_data_url)) return json.loads(fetch_remote_content(spdx_data_url))

View File

@ -209,6 +209,7 @@ class PackageSpec(object): # pylint: disable=too-many-instance-attributes
raw = raw.strip() raw = raw.strip()
parsers = ( parsers = (
self._parse_local_file,
self._parse_requirements, self._parse_requirements,
self._parse_custom_name, self._parse_custom_name,
self._parse_id, self._parse_id,
@ -227,10 +228,16 @@ class PackageSpec(object): # pylint: disable=too-many-instance-attributes
# the leftover is a package name # the leftover is a package name
self.name = raw self.name = raw
def _parse_requirements(self, raw): @staticmethod
if "@" not in raw: def _parse_local_file(raw):
if raw.startswith("file://") or not any(c in raw for c in ("/", "\\")):
return raw return raw
if raw.startswith("file://") and os.path.exists(raw[7:]): if os.path.exists(raw):
return "file://%s" % raw
return raw
def _parse_requirements(self, raw):
if "@" not in raw or raw.startswith("file://"):
return raw return raw
tokens = raw.rsplit("@", 1) tokens = raw.rsplit("@", 1)
if any(s in tokens[1] for s in (":", "/")): if any(s in tokens[1] for s in (":", "/")):

View File

@ -51,7 +51,9 @@ class PackagePacker(object):
r"[^\da-zA-Z\-\._\+]+", r"[^\da-zA-Z\-\._\+]+",
"", "",
"{name}{system}-{version}.tar.gz".format( "{name}{system}-{version}.tar.gz".format(
name=name, system=("-" + system) if system else "", version=version, name=name,
system=("-" + system) if system else "",
version=version,
), ),
) )

View File

@ -94,7 +94,7 @@ class PlatformBase( # pylint: disable=too-many-instance-attributes,too-many-pub
name = item name = item
version = "*" version = "*"
if "@" in item: if "@" in item:
name, version = item.split("@", 2) name, version = item.split("@", 1)
spec = self.pm.ensure_spec(name) spec = self.pm.ensure_spec(name)
options = {"version": version.strip(), "optional": False} options = {"version": version.strip(), "optional": False}
if spec.owner: if spec.owner:

View File

@ -301,7 +301,11 @@ def on_command():
def on_exception(e): def on_exception(e):
skip_conditions = [ skip_conditions = [
isinstance(e, cls) isinstance(e, cls)
for cls in (IOError, exception.ReturnErrorCode, exception.UserSideException,) for cls in (
IOError,
exception.ReturnErrorCode,
exception.UserSideException,
)
] ]
if any(skip_conditions): if any(skip_conditions):
return return

View File

@ -52,7 +52,7 @@ setup(
[">=2.7", "!=3.0.*", "!=3.1.*", "!=3.2.*", "!=3.3.*", "!=3.4.*"] [">=2.7", "!=3.0.*", "!=3.1.*", "!=3.2.*", "!=3.3.*", "!=3.4.*"]
), ),
install_requires=install_requires, install_requires=install_requires,
packages=find_packages() + ["scripts"], packages=find_packages(exclude=["tests.*", "tests"]) + ["scripts"],
package_data={ package_data={
"platformio": [ "platformio": [
"ide/tpls/*/.*.tpl", "ide/tpls/*/.*.tpl",

View File

@ -100,14 +100,21 @@ def test_account_register(
def test_account_login( def test_account_login(
clirunner, validate_cliresult, isolated_pio_core, clirunner,
validate_cliresult,
isolated_pio_core,
): ):
result = clirunner.invoke(cmd_account, ["login", "-u", username, "-p", password],) result = clirunner.invoke(
cmd_account,
["login", "-u", username, "-p", password],
)
validate_cliresult(result) validate_cliresult(result)
def test_account_summary( def test_account_summary(
clirunner, validate_cliresult, isolated_pio_core, clirunner,
validate_cliresult,
isolated_pio_core,
): ):
result = clirunner.invoke(cmd_account, ["show", "--json-output", "--offline"]) result = clirunner.invoke(cmd_account, ["show", "--json-output", "--offline"])
validate_cliresult(result) validate_cliresult(result)
@ -160,13 +167,21 @@ def test_account_summary(
def test_account_token(clirunner, validate_cliresult, isolated_pio_core): def test_account_token(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke(cmd_account, ["token", "--password", password,],) result = clirunner.invoke(
cmd_account,
[
"token",
"--password",
password,
],
)
validate_cliresult(result) validate_cliresult(result)
assert "Personal Authentication Token:" in result.output assert "Personal Authentication Token:" in result.output
token = result.output.strip().split(": ")[-1] token = result.output.strip().split(": ")[-1]
result = clirunner.invoke( result = clirunner.invoke(
cmd_account, ["token", "--password", password, "--json-output"], cmd_account,
["token", "--password", password, "--json-output"],
) )
validate_cliresult(result) validate_cliresult(result)
json_result = json.loads(result.output.strip()) json_result = json.loads(result.output.strip())
@ -177,7 +192,14 @@ def test_account_token(clirunner, validate_cliresult, isolated_pio_core):
clirunner.invoke(cmd_account, ["logout"]) clirunner.invoke(cmd_account, ["logout"])
result = clirunner.invoke(cmd_account, ["token", "--password", password,],) result = clirunner.invoke(
cmd_account,
[
"token",
"--password",
password,
],
)
assert result.exit_code > 0 assert result.exit_code > 0
assert result.exception assert result.exception
assert "You are not authorized! Please log in to PIO Account" in str( assert "You are not authorized! Please log in to PIO Account" in str(
@ -187,7 +209,8 @@ def test_account_token(clirunner, validate_cliresult, isolated_pio_core):
os.environ["PLATFORMIO_AUTH_TOKEN"] = token os.environ["PLATFORMIO_AUTH_TOKEN"] = token
result = clirunner.invoke( result = clirunner.invoke(
cmd_account, ["token", "--password", password, "--json-output"], cmd_account,
["token", "--password", password, "--json-output"],
) )
validate_cliresult(result) validate_cliresult(result)
json_result = json.loads(result.output.strip()) json_result = json.loads(result.output.strip())
@ -197,7 +220,10 @@ def test_account_token(clirunner, validate_cliresult, isolated_pio_core):
os.environ.pop("PLATFORMIO_AUTH_TOKEN") os.environ.pop("PLATFORMIO_AUTH_TOKEN")
result = clirunner.invoke(cmd_account, ["login", "-u", username, "-p", password],) result = clirunner.invoke(
cmd_account,
["login", "-u", username, "-p", password],
)
validate_cliresult(result) validate_cliresult(result)
@ -205,7 +231,13 @@ def test_account_change_password(clirunner, validate_cliresult, isolated_pio_cor
new_password = "Testpassword123" new_password = "Testpassword123"
result = clirunner.invoke( result = clirunner.invoke(
cmd_account, cmd_account,
["password", "--old-password", password, "--new-password", new_password,], [
"password",
"--old-password",
password,
"--new-password",
new_password,
],
) )
validate_cliresult(result) validate_cliresult(result)
assert "Password successfully changed!" in result.output assert "Password successfully changed!" in result.output
@ -213,13 +245,20 @@ def test_account_change_password(clirunner, validate_cliresult, isolated_pio_cor
clirunner.invoke(cmd_account, ["logout"]) clirunner.invoke(cmd_account, ["logout"])
result = clirunner.invoke( result = clirunner.invoke(
cmd_account, ["login", "-u", username, "-p", new_password], cmd_account,
["login", "-u", username, "-p", new_password],
) )
validate_cliresult(result) validate_cliresult(result)
result = clirunner.invoke( result = clirunner.invoke(
cmd_account, cmd_account,
["password", "--old-password", new_password, "--new-password", password,], [
"password",
"--old-password",
new_password,
"--new-password",
password,
],
) )
validate_cliresult(result) validate_cliresult(result)
@ -272,14 +311,20 @@ def test_account_update(
link = link.replace("&amp;", "&") link = link.replace("&amp;", "&")
session.get(link) session.get(link)
result = clirunner.invoke(cmd_account, ["show"],) result = clirunner.invoke(
cmd_account,
["show"],
)
assert result.exit_code > 0 assert result.exit_code > 0
assert result.exception assert result.exception
assert "You are not authorized! Please log in to PIO Account" in str( assert "You are not authorized! Please log in to PIO Account" in str(
result.exception result.exception
) )
result = clirunner.invoke(cmd_account, ["login", "-u", username, "-p", password],) result = clirunner.invoke(
cmd_account,
["login", "-u", username, "-p", password],
)
validate_cliresult(result) validate_cliresult(result)
@ -317,7 +362,8 @@ def test_account_update(
def test_org_create(clirunner, validate_cliresult, isolated_pio_core): def test_org_create(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke( result = clirunner.invoke(
cmd_org, ["create", "--email", email, "--displayname", display_name, orgname], cmd_org,
["create", "--email", email, "--displayname", display_name, orgname],
) )
validate_cliresult(result) validate_cliresult(result)
@ -405,13 +451,21 @@ def test_org_update(clirunner, validate_cliresult, isolated_pio_core):
def test_team_create(clirunner, validate_cliresult, isolated_pio_core): def test_team_create(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke( result = clirunner.invoke(
cmd_team, cmd_team,
["create", "%s:%s" % (orgname, teamname), "--description", team_description,], [
"create",
"%s:%s" % (orgname, teamname),
"--description",
team_description,
],
) )
validate_cliresult(result) validate_cliresult(result)
def test_team_list(clirunner, validate_cliresult, isolated_pio_core): def test_team_list(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke(cmd_team, ["list", "%s" % orgname, "--json-output"],) result = clirunner.invoke(
cmd_team,
["list", "%s" % orgname, "--json-output"],
)
validate_cliresult(result) validate_cliresult(result)
json_result = json.loads(result.output.strip()) json_result = json.loads(result.output.strip())
for item in json_result: for item in json_result:
@ -423,22 +477,30 @@ def test_team_list(clirunner, validate_cliresult, isolated_pio_core):
def test_team_add_member(clirunner, validate_cliresult, isolated_pio_core): def test_team_add_member(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke( result = clirunner.invoke(
cmd_team, ["add", "%s:%s" % (orgname, teamname), second_username], cmd_team,
["add", "%s:%s" % (orgname, teamname), second_username],
) )
validate_cliresult(result) validate_cliresult(result)
result = clirunner.invoke(cmd_team, ["list", "%s" % orgname, "--json-output"],) result = clirunner.invoke(
cmd_team,
["list", "%s" % orgname, "--json-output"],
)
validate_cliresult(result) validate_cliresult(result)
assert second_username in result.output assert second_username in result.output
def test_team_remove(clirunner, validate_cliresult, isolated_pio_core): def test_team_remove(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke( result = clirunner.invoke(
cmd_team, ["remove", "%s:%s" % (orgname, teamname), second_username], cmd_team,
["remove", "%s:%s" % (orgname, teamname), second_username],
) )
validate_cliresult(result) validate_cliresult(result)
result = clirunner.invoke(cmd_team, ["list", "%s" % orgname, "--json-output"],) result = clirunner.invoke(
cmd_team,
["list", "%s" % orgname, "--json-output"],
)
validate_cliresult(result) validate_cliresult(result)
assert second_username not in result.output assert second_username not in result.output
@ -459,7 +521,10 @@ def test_team_update(clirunner, validate_cliresult, receive_email, isolated_pio_
) )
validate_cliresult(result) validate_cliresult(result)
result = clirunner.invoke(cmd_team, ["list", "%s" % orgname, "--json-output"],) result = clirunner.invoke(
cmd_team,
["list", "%s" % orgname, "--json-output"],
)
validate_cliresult(result) validate_cliresult(result)
json_result = json.loads(result.output.strip()) json_result = json.loads(result.output.strip())
for item in json_result: for item in json_result:

View File

@ -446,7 +446,10 @@ int main() {
result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir)]) result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir)])
validate_cliresult(result) validate_cliresult(result)
defects = sum(count_defects(result.output)) defects = sum(count_defects(result.output))
assert defects > 0, "Failed %s with %s" % (framework, tool,) assert defects > 0, "Failed %s with %s" % (
framework,
tool,
)
def test_check_skip_includes_from_packages(clirunner, validate_cliresult, tmpdir): def test_check_skip_includes_from_packages(clirunner, validate_cliresult, tmpdir):

View File

@ -339,14 +339,17 @@ def test_lib_stats(clirunner, validate_cliresult):
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(
"dlweek", [
"added", "dlweek",
"updated", "added",
"topkeywords", "updated",
"dlmonth", "topkeywords",
"dlday", "dlmonth",
"lastkeywords", "dlday",
] "lastkeywords",
) == set(json.loads(result.output).keys()) ]
)
== set(json.loads(result.output).keys())
)

View File

@ -60,7 +60,8 @@ def test_install_unknown_from_registry(clirunner):
def test_install_core_3_dev_platform(clirunner, validate_cliresult, isolated_pio_core): def test_install_core_3_dev_platform(clirunner, validate_cliresult, isolated_pio_core):
result = clirunner.invoke( result = clirunner.invoke(
cli_platform.platform_install, ["atmelavr@1.2.0", "--skip-default-package"], cli_platform.platform_install,
["atmelavr@1.2.0", "--skip-default-package"],
) )
assert result.exit_code == 0 assert result.exit_code == 0

View File

@ -77,7 +77,8 @@ void loop() {}
) )
result = clirunner.invoke( result = clirunner.invoke(
cmd_test, ["-d", str(project_dir), "--without-testing", "--without-uploading"], cmd_test,
["-d", str(project_dir), "--without-testing", "--without-uploading"],
) )
validate_cliresult(result) validate_cliresult(result)
@ -127,7 +128,8 @@ int main() {
) )
native_result = clirunner.invoke( native_result = clirunner.invoke(
cmd_test, ["-d", str(project_dir), "-e", "native"], cmd_test,
["-d", str(project_dir), "-e", "native"],
) )
test_dir.join("unittest_transport.h").write( test_dir.join("unittest_transport.h").write(

View File

@ -230,6 +230,41 @@ def test_install_from_registry(isolated_pio_core, tmpdir_factory):
tm.install("owner/unknown-package-tool", silent=True) tm.install("owner/unknown-package-tool", silent=True)
def test_install_lib_depndencies(isolated_pio_core, tmpdir_factory):
tmp_dir = tmpdir_factory.mktemp("tmp")
src_dir = tmp_dir.join("lib-with-deps").mkdir()
root_dir = src_dir.mkdir("root")
root_dir.mkdir("src").join("main.cpp").write("#include <stdio.h>")
root_dir.join("library.json").write(
"""
{
"name": "lib-with-deps",
"version": "2.0.0",
"dependencies": [
{
"owner": "bblanchon",
"name": "ArduinoJson",
"version": "^6.16.1"
},
{
"name": "external-repo",
"version": "https://github.com/milesburton/Arduino-Temperature-Control-Library.git#4a0ccc1"
}
]
}
"""
)
lm = LibraryPackageManager(str(tmpdir_factory.mktemp("lib-storage")))
lm.install("file://%s" % str(src_dir), silent=True)
installed = lm.get_installed()
assert len(installed) == 4
assert set(["external-repo", "ArduinoJson", "lib-with-deps", "OneWire"]) == set(
p.metadata.name for p in installed
)
def test_install_force(isolated_pio_core, tmpdir_factory): def test_install_force(isolated_pio_core, tmpdir_factory):
lm = LibraryPackageManager(str(tmpdir_factory.mktemp("lib-storage"))) lm = LibraryPackageManager(str(tmpdir_factory.mktemp("lib-storage")))
# install #64 ArduinoJson # install #64 ArduinoJson

View File

@ -44,7 +44,7 @@ def test_library_json_parser():
"dependencies": { "dependencies": {
"deps1": "1.2.0", "deps1": "1.2.0",
"deps2": "https://github.com/username/package.git", "deps2": "https://github.com/username/package.git",
"@owner/deps3": "^2.1.3" "owner/deps3": "^2.1.3"
}, },
"customField": "Custom Value" "customField": "Custom Value"
} }
@ -65,9 +65,9 @@ def test_library_json_parser():
"homepage": "http://old.url.format", "homepage": "http://old.url.format",
"build": {"flags": ["-DHELLO"]}, "build": {"flags": ["-DHELLO"]},
"dependencies": [ "dependencies": [
{"name": "@owner/deps3", "version": "^2.1.3"},
{"name": "deps1", "version": "1.2.0"}, {"name": "deps1", "version": "1.2.0"},
{"name": "deps2", "version": "https://github.com/username/package.git"}, {"name": "deps2", "version": "https://github.com/username/package.git"},
{"owner": "owner", "name": "deps3", "version": "^2.1.3"},
], ],
"customField": "Custom Value", "customField": "Custom Value",
}, },
@ -83,7 +83,7 @@ def test_library_json_parser():
}, },
"dependencies": [ "dependencies": [
{"name": "deps1", "version": "1.0.0"}, {"name": "deps1", "version": "1.0.0"},
{"name": "@owner/deps2", "version": "1.0.0", "platforms": "*", "frameworks": "arduino, espidf"}, {"owner": "owner", "name": "deps2", "version": "1.0.0", "platforms": "*", "frameworks": "arduino, espidf"},
{"name": "deps3", "version": "1.0.0", "platforms": ["ststm32", "sifive"]} {"name": "deps3", "version": "1.0.0", "platforms": ["ststm32", "sifive"]}
] ]
} }
@ -98,13 +98,14 @@ def test_library_json_parser():
"export": {"exclude": ["audio_samples"]}, "export": {"exclude": ["audio_samples"]},
"platforms": ["atmelavr"], "platforms": ["atmelavr"],
"dependencies": [ "dependencies": [
{"name": "deps1", "version": "1.0.0"},
{ {
"name": "@owner/deps2", "owner": "owner",
"name": "deps2",
"version": "1.0.0", "version": "1.0.0",
"platforms": ["*"], "platforms": ["*"],
"frameworks": ["arduino", "espidf"], "frameworks": ["arduino", "espidf"],
}, },
{"name": "deps1", "version": "1.0.0"},
{ {
"name": "deps3", "name": "deps3",
"version": "1.0.0", "version": "1.0.0",
@ -115,16 +116,16 @@ def test_library_json_parser():
) )
raw_data = parser.LibraryJsonManifestParser( raw_data = parser.LibraryJsonManifestParser(
'{"dependencies": ["dep1", "dep2", "@owner/dep3"]}' '{"dependencies": ["dep1", "dep2", "owner/dep3@1.2.3"]}'
).as_dict() ).as_dict()
raw_data["dependencies"] = sorted(raw_data["dependencies"], key=lambda a: a["name"]) raw_data["dependencies"] = sorted(raw_data["dependencies"], key=lambda a: a["name"])
assert not jsondiff.diff( assert not jsondiff.diff(
raw_data, raw_data,
{ {
"dependencies": [ "dependencies": [
{"name": "@owner/dep3"},
{"name": "dep1"}, {"name": "dep1"},
{"name": "dep2"}, {"name": "dep2"},
{"name": "owner/dep3@1.2.3"},
], ],
}, },
) )

View File

@ -90,12 +90,13 @@ def test_spec_local_urls(tmpdir_factory):
assert PackageSpec("file:///tmp/some-lib/") == PackageSpec( assert PackageSpec("file:///tmp/some-lib/") == PackageSpec(
url="file:///tmp/some-lib/", name="some-lib" url="file:///tmp/some-lib/", name="some-lib"
) )
assert PackageSpec("file:///tmp/foo.tar.gz@~2.3.0-beta.1") == PackageSpec( # detached package
url="file:///tmp/foo.tar.gz", name="foo", requirements="~2.3.0-beta.1" assert PackageSpec("file:///tmp/some-lib@src-67e1043a673d2") == PackageSpec(
url="file:///tmp/some-lib@src-67e1043a673d2", name="some-lib"
) )
# detached folder with "@" symbol # detached folder without scheme
pkg_dir = tmpdir_factory.mktemp("storage").join("detached@1.2.3").mkdir() pkg_dir = tmpdir_factory.mktemp("storage").join("detached@1.2.3").mkdir()
assert PackageSpec("file://%s" % str(pkg_dir)) == PackageSpec( assert PackageSpec(str(pkg_dir)) == PackageSpec(
name="detached", url="file://%s" % pkg_dir name="detached", url="file://%s" % pkg_dir
) )