# Copyright (c) 2014-present PlatformIO # # 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 fs, telemetry, util from platformio.compat import PY2 from platformio.debug.exception import DebugInvalidOptionsError, DebugSupportError from platformio.exception import UserSideException from platformio.platform.exception import InvalidBoardManifest class PlatformBoardConfig(object): def __init__(self, manifest_path): self._id = os.path.basename(manifest_path)[:-5] assert os.path.isfile(manifest_path) self.manifest_path = manifest_path try: self._manifest = fs.load_json(manifest_path) except ValueError: raise InvalidBoardManifest(manifest_path) if not set(["name", "url", "vendor"]) <= set(self._manifest): raise UserSideException( "Please specify name, url and vendor fields for " + manifest_path ) def get(self, path, default=None): try: value = self._manifest for k in path.split("."): value = value[k] # pylint: disable=undefined-variable if PY2 and isinstance(value, unicode): # cast to plain string from unicode for PY2, resolves issue in # dev/platform when BoardConfig.get() is used in pair with # os.path.join(file_encoding, unicode_encoding) try: value = value.encode("utf-8") except UnicodeEncodeError: pass return value except KeyError: if default is not None: return default raise KeyError("Invalid board option '%s'" % path) def update(self, path, value): newdict = None for key in path.split(".")[::-1]: if newdict is None: newdict = {key: value} else: newdict = {key: newdict} util.merge_dicts(self._manifest, newdict) def __contains__(self, key): try: self.get(key) return True except KeyError: return False @property def id(self): return self._id @property def id_(self): return self.id @property def manifest(self): return self._manifest def get_brief_data(self): result = { "id": self.id, "name": self._manifest["name"], "platform": self._manifest.get("platform"), "mcu": self._manifest.get("build", {}).get("mcu", "").upper(), "fcpu": int( "".join( [ c for c in str(self._manifest.get("build", {}).get("f_cpu", "0L")) if c.isdigit() ] ) ), "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"], } if self._manifest.get("connectivity"): result["connectivity"] = self._manifest.get("connectivity") debug = self.get_debug_data() if debug: result["debug"] = debug return result def get_debug_data(self): if not self._manifest.get("debug", {}).get("tools"): return None tools = {} for name, options in self._manifest["debug"]["tools"].items(): tools[name] = {} for key, value in options.items(): if key in ("default", "onboard") and value: tools[name][key] = value return {"tools": tools} def get_debug_tool_name(self, custom=None): debug_tools = self._manifest.get("debug", {}).get("tools") tool_name = custom if tool_name == "custom": return tool_name if not debug_tools: telemetry.send_event("Debug", "Request", self.id) raise DebugSupportError(self._manifest["name"]) if tool_name: if tool_name in debug_tools: return tool_name raise DebugInvalidOptionsError( "Unknown debug tool `%s`. Please use one of `%s` or `custom`" % (tool_name, ", ".join(sorted(list(debug_tools)))) ) # automatically select best tool data = {"default": [], "onboard": [], "external": []} for key, value in debug_tools.items(): if value.get("default"): data["default"].append(key) elif value.get("onboard"): data["onboard"].append(key) data["external"].append(key) for key, value in data.items(): if not value: continue return sorted(value)[0] assert any(item for item in data)