diff --git a/platformio/commands/boards.py b/platformio/commands/boards.py index 1a5c258d..07b800a0 100644 --- a/platformio/commands/boards.py +++ b/platformio/commands/boards.py @@ -16,6 +16,7 @@ import json import click +from platformio.exception import APIRequestError from platformio.managers.platform import PlatformManager @@ -78,24 +79,24 @@ def cli(query, installed, json_output): # pylint: disable=R0912 def _get_boards(installed=False): - boards = PlatformManager.get_registered_boards() - if installed: - _installed_boards = [ - "%s:%s" % (b['platform'], b['id']) - for b in PlatformManager().get_installed_boards() - ] - _new_boards = [] - for board in boards: + boards = PlatformManager().get_installed_boards() + if not installed: + know_boards = ["%s:%s" % (b['platform'], b['id']) for b in boards] + for board in PlatformManager().get_registered_boards(): key = "%s:%s" % (board['platform'], board['id']) - if key in _installed_boards: - _new_boards.append(board) - boards = _new_boards + if key not in know_boards: + boards.append(board) return boards def _ouput_boards_json(query, installed=False): result = [] - for board in _get_boards(installed): + try: + boards = _get_boards(installed) + except APIRequestError: + if not installed: + boards = _get_boards(True) + for board in boards: if query: search_data = "%s %s" % (board['id'], json.dumps(board).lower()) if query.lower() not in search_data.lower(): diff --git a/platformio/maintenance.py b/platformio/maintenance.py index ac056bdf..c91857dc 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -12,12 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -import re -import struct +import json +import os from os import getenv +from os.path import isdir, join from time import time import click +import semantic_version from platformio import __version__, app, exception, telemetry, util from platformio.commands.lib import lib_update as cmd_libraries_update @@ -65,21 +67,13 @@ def on_platformio_exception(e): class Upgrader(object): def __init__(self, from_version, to_version): - self.from_version = self.version_to_int(from_version) - self.to_version = self.version_to_int(to_version) + self.from_version = semantic_version.Version.coerce(from_version) + self.to_version = semantic_version.Version.coerce(to_version) self._upgraders = [ - (self.version_to_int("3.0.0"), self._upgrade_to_3_0_0) + (semantic_version.Version("3.0.0"), self._upgrade_to_3_0_0) ] - @staticmethod - def version_to_int(version): - match = re.match(r"(\d+)\.(\d+)\.(\d+)(\D+)?", version) - assert match is not None and len(match.groups()) is 4 - verchrs = [chr(int(match.group(i))) for i in range(1, 4)] - verchrs.append(chr(255 if match.group(4) is None else 0)) - return struct.unpack(">I", "".join(verchrs)) - def run(self, ctx): if self.from_version > self.to_version: return True @@ -93,9 +87,26 @@ class Upgrader(object): return all(result) def _upgrade_to_3_0_0(self, ctx): # pylint: disable=R0201 + # convert custom board configuration + boards_dir = join(util.get_home_dir(), "boards") + if isdir(boards_dir): + for item in os.listdir(boards_dir): + if not item.endswith(".json"): + continue + data = util.load_json(join(boards_dir, item)) + if set(["name", "url", "vendor"]) <= set(data.keys()): + continue + os.remove(join(boards_dir, item)) + for key, value in data.items(): + with open(join(boards_dir, "%s.json" % key), + "w") as f: + json.dump(value, f, sort_keys=True, indent=2) + + # re-install PlatformIO 2.0 development platforms installed_platforms = app.get_state_item("installed_platforms", []) if installed_platforms: ctx.invoke(cmd_platform_install, platforms=installed_platforms) + return True @@ -169,9 +180,8 @@ def check_platformio_upgrade(): app.set_state_item("last_check", last_check) latest_version = get_latest_version() - if (latest_version == __version__ or - Upgrader.version_to_int(latest_version) < - Upgrader.version_to_int(__version__)): + if (semantic_version.Version.coerce(latest_version) <= + semantic_version.Version.coerce(__version__)): return terminal_width, _ = click.get_terminal_size() diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 4fab1720..649166ef 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -98,11 +98,8 @@ class PlatformManager(PackageManager): boards = [] for manifest in self.get_installed(): p = PlatformFactory.newPlatform(manifest['_manifest_path']) - for id_, config in p.get_boards().items(): - manifest = config.get_manifest().copy() - manifest['id'] = id_ - manifest['platform'] = p.name - boards.append(manifest) + for config in p.get_boards().values(): + boards.append(config.get_brief_data()) return boards @staticmethod @@ -394,22 +391,37 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): return False def get_boards(self, id_=None): + + def _append_board(board_id, manifest_path): + config = PlatformBoardConfig(manifest_path) + if "platform" in config and config.get("platform") != self.name: + return + elif ("platforms" in config and + self.name not in config.get("platforms")): + return + config.manifest['platform'] = self.name + self._BOARDS_CACHE[board_id] = config + + bdirs = (join(util.get_home_dir(), "boards"), + join(self.get_dir(), "boards")) if id_ is None: - boards_dir = join(self.get_dir(), "boards") - if not isdir(boards_dir): - return {} - for item in sorted(os.listdir(boards_dir)): - _id = item[:-5] - if _id in self._BOARDS_CACHE: + for boards_dir in bdirs: + if not isdir(boards_dir): continue - self._BOARDS_CACHE[_id] = PlatformBoardConfig( - join(self.get_dir(), "boards", item) - ) + for item in sorted(os.listdir(boards_dir)): + _id = item[:-5] + if not item.endswith(".json") or _id in self._BOARDS_CACHE: + continue + _append_board(_id, join(boards_dir, item)) else: if id_ not in self._BOARDS_CACHE: - self._BOARDS_CACHE[id_] = PlatformBoardConfig( - join(self.get_dir(), "boards", "%s.json" % id_) - ) + for boards_dir in bdirs: + manifest_path = join(bdirs, "%s.json" % id_) + if not isfile(manifest_path): + continue + _append_board(id_, manifest_path) + if id_ not in self._BOARDS_CACHE: + raise exception.UnknownBoard(id_) return self._BOARDS_CACHE[id_] if id_ else self._BOARDS_CACHE def board_config(self, id_): @@ -472,10 +484,11 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): class PlatformBoardConfig(object): def __init__(self, manifest_path): - if not isfile(manifest_path): - raise exception.UnknownBoard(basename(manifest_path[:-5])) + self._id = basename(manifest_path)[:-5] + assert isfile(manifest_path) self.manifest_path = manifest_path self._manifest = util.load_json(manifest_path) + assert set(["name", "url", "vendor"]) <= set(self._manifest.keys()) def get(self, path, default=None): try: @@ -496,5 +509,24 @@ class PlatformBoardConfig(object): except KeyError: return False - def get_manifest(self): + @property + def id_(self): + return self._id + + @property + def manifest(self): return self._manifest + + def get_brief_data(self): + return { + "id": self.id_, + "name": self._manifest['name'], + "platform": self._manifest.get("platform"), + "mcu": self._manifest.get("build", {}).get("mcu", "").upper(), + "fcpu": int(self._manifest.get("build", {}).get("f_cpu", "")[:-1]), + "ram": self._manifest.get("upload", {}).get("maximum_ram_size", 0), + "rom": self._manifest.get("upload", {}).get("maximum_size", 0), + "frameworks": self._manifest.get("frameworks"), + "vendor": self._manifest['vendor'], + "url": self._manifest['url'] + }