forked from platformio/platformio-core
Switch to the new ProjectConfig API
This commit is contained in:
@ -25,6 +25,7 @@ from platformio.commands.init import cli as cmd_init
|
||||
from platformio.commands.init import validate_boards
|
||||
from platformio.commands.run import cli as cmd_run
|
||||
from platformio.exception import CIBuildEnvsEmpty
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
|
||||
def validate_path(ctx, param, value): # pylint: disable=unused-argument
|
||||
@ -161,8 +162,8 @@ def _exclude_contents(dst_dir, patterns):
|
||||
|
||||
|
||||
def _copy_project_conf(build_dir, project_conf):
|
||||
config = util.load_project_config(project_conf)
|
||||
config = ProjectConfig(project_conf, parse_extra=False)
|
||||
if config.has_section("platformio"):
|
||||
config.remove_section("platformio")
|
||||
with open(join(build_dir, "platformio.ini"), "w") as fp:
|
||||
with open(join(build_dir, "platformio.ini"), "wb") as fp:
|
||||
config.write(fp)
|
||||
|
@ -15,11 +15,13 @@
|
||||
import json
|
||||
import sys
|
||||
from os import getcwd
|
||||
from os.path import join
|
||||
|
||||
import click
|
||||
from serial.tools import miniterm
|
||||
|
||||
from platformio import exception, util
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
|
||||
@click.group(short_help="Monitor device or list existing")
|
||||
@ -161,11 +163,10 @@ def device_list( # pylint: disable=too-many-branches
|
||||
help="Load configuration from `platformio.ini` and specified environment")
|
||||
def device_monitor(**kwargs): # pylint: disable=too-many-branches
|
||||
try:
|
||||
project_options = get_project_options(kwargs['project_dir'],
|
||||
monitor_options = get_project_options(kwargs['project_dir'],
|
||||
kwargs['environment'])
|
||||
monitor_options = {k: v for k, v in project_options or []}
|
||||
if monitor_options:
|
||||
for k in ("port", "baud", "speed", "rts", "dtr"):
|
||||
for k in ("port", "speed", "rts", "dtr"):
|
||||
k2 = "monitor_%s" % k
|
||||
if k == "speed":
|
||||
k = "baud"
|
||||
@ -205,24 +206,13 @@ def device_monitor(**kwargs): # pylint: disable=too-many-branches
|
||||
raise exception.MinitermException(e)
|
||||
|
||||
|
||||
def get_project_options(project_dir, environment):
|
||||
config = util.load_project_config(project_dir)
|
||||
if not config.sections():
|
||||
return None
|
||||
|
||||
known_envs = [s[4:] for s in config.sections() if s.startswith("env:")]
|
||||
if environment:
|
||||
if environment in known_envs:
|
||||
return config.items("env:%s" % environment)
|
||||
raise exception.UnknownEnvNames(environment, ", ".join(known_envs))
|
||||
|
||||
if not known_envs:
|
||||
return None
|
||||
|
||||
if config.has_option("platformio", "env_default"):
|
||||
env_default = config.get("platformio",
|
||||
"env_default").split(", ")[0].strip()
|
||||
if env_default and env_default in known_envs:
|
||||
return config.items("env:%s" % env_default)
|
||||
|
||||
return config.items("env:%s" % known_envs[0])
|
||||
def get_project_options(project_dir, environment=None):
|
||||
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
|
||||
config.validate(envs=[environment] if environment else None)
|
||||
if not environment:
|
||||
default_envs = config.default_envs()
|
||||
if default_envs:
|
||||
environment = default_envs[0]
|
||||
else:
|
||||
environment = config.envs()[0]
|
||||
return {k: v for k, v in config.items(env=environment)}
|
||||
|
@ -23,9 +23,9 @@ import click
|
||||
from platformio import exception, util
|
||||
from platformio.commands.platform import \
|
||||
platform_install as cli_platform_install
|
||||
from platformio.commands.run import check_project_envs
|
||||
from platformio.ide.projectgenerator import ProjectGenerator
|
||||
from platformio.managers.platform import PlatformManager
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
|
||||
def validate_boards(ctx, param, value): # pylint: disable=W0613
|
||||
@ -128,14 +128,11 @@ def cli(
|
||||
|
||||
|
||||
def get_best_envname(project_dir, boards=None):
|
||||
config = util.load_project_config(project_dir)
|
||||
env_default = None
|
||||
if config.has_option("platformio", "env_default"):
|
||||
env_default = util.parse_conf_multi_values(
|
||||
config.get("platformio", "env_default"))
|
||||
check_project_envs(config, env_default)
|
||||
if env_default:
|
||||
return env_default[0]
|
||||
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
||||
config.validate()
|
||||
default_envs = config.default_envs()
|
||||
if default_envs:
|
||||
return default_envs[0]
|
||||
section = None
|
||||
for section in config.sections():
|
||||
if not section.startswith("env:"):
|
||||
@ -369,7 +366,8 @@ def fill_project_envs(ctx, project_dir, board_ids, project_option, env_prefix,
|
||||
used_boards = []
|
||||
used_platforms = []
|
||||
|
||||
config = util.load_project_config(project_dir)
|
||||
config_path = join(project_dir, "platformio.ini")
|
||||
config = util.load_project_config(config_path)
|
||||
for section in config.sections():
|
||||
cond = [
|
||||
section.startswith("env:"),
|
||||
@ -409,10 +407,12 @@ def fill_project_envs(ctx, project_dir, board_ids, project_option, env_prefix,
|
||||
if not content:
|
||||
return
|
||||
|
||||
with open(join(project_dir, "platformio.ini"), "a") as f:
|
||||
with open(config_path, "a") as f:
|
||||
content.append("")
|
||||
f.write("\n".join(content))
|
||||
|
||||
ProjectConfig.reset_instances()
|
||||
|
||||
|
||||
def _install_dependent_platforms(ctx, platforms):
|
||||
installed_platforms = [
|
||||
|
@ -26,6 +26,7 @@ from platformio.commands.platform import \
|
||||
platform_install as cmd_platform_install
|
||||
from platformio.managers.lib import LibraryManager, is_builtin_lib
|
||||
from platformio.managers.platform import PlatformFactory
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
|
||||
|
||||
@ -54,9 +55,6 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose,
|
||||
if isfile(project_dir):
|
||||
project_dir = util.find_project_dir_above(project_dir)
|
||||
|
||||
if not util.is_platformio_project(project_dir):
|
||||
raise exception.NotPlatformIOProject(project_dir)
|
||||
|
||||
with util.cd(project_dir):
|
||||
# clean obsolete build dir
|
||||
if not disable_auto_clean:
|
||||
@ -69,25 +67,17 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose,
|
||||
util.get_projectbuild_dir(force=True),
|
||||
fg="yellow")
|
||||
|
||||
config = util.load_project_config()
|
||||
env_default = None
|
||||
if config.has_option("platformio", "env_default"):
|
||||
env_default = util.parse_conf_multi_values(
|
||||
config.get("platformio", "env_default"))
|
||||
|
||||
check_project_defopts(config)
|
||||
check_project_envs(config, environment or env_default)
|
||||
config = ProjectConfig.get_instance(
|
||||
join(project_dir, "platformio.ini"))
|
||||
config.validate()
|
||||
|
||||
results = []
|
||||
start_time = time()
|
||||
for section in config.sections():
|
||||
if not section.startswith("env:"):
|
||||
continue
|
||||
|
||||
envname = section[4:]
|
||||
default_envs = config.default_envs()
|
||||
for envname in config.envs():
|
||||
skipenv = any([
|
||||
environment and envname not in environment, not environment
|
||||
and env_default and envname not in env_default
|
||||
and default_envs and envname not in default_envs
|
||||
])
|
||||
if skipenv:
|
||||
results.append((envname, None))
|
||||
@ -97,7 +87,7 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose,
|
||||
click.echo()
|
||||
|
||||
options = {}
|
||||
for k, v in config.items(section):
|
||||
for k, v in config.items(env=envname):
|
||||
options[k] = v
|
||||
if "piotest" not in options and "piotest" in ctx.meta:
|
||||
options['piotest'] = ctx.meta['piotest']
|
||||
@ -127,26 +117,6 @@ class EnvironmentProcessor(object):
|
||||
|
||||
DEFAULT_DUMP_OPTIONS = ("platform", "framework", "board")
|
||||
|
||||
KNOWN_PLATFORMIO_OPTIONS = [
|
||||
"description", "env_default", "home_dir", "lib_dir", "libdeps_dir",
|
||||
"include_dir", "src_dir", "build_dir", "data_dir", "test_dir",
|
||||
"boards_dir", "lib_extra_dirs", "extra_configs"
|
||||
]
|
||||
|
||||
KNOWN_ENV_OPTIONS = [
|
||||
"platform", "framework", "board", "build_flags", "src_build_flags",
|
||||
"build_unflags", "src_filter", "extra_scripts", "targets",
|
||||
"upload_port", "upload_protocol", "upload_speed", "upload_flags",
|
||||
"upload_resetmethod", "lib_deps", "lib_ignore", "lib_extra_dirs",
|
||||
"lib_ldf_mode", "lib_compat_mode", "lib_archive", "piotest",
|
||||
"test_transport", "test_filter", "test_ignore", "test_port",
|
||||
"test_speed", "test_build_project_src", "debug_tool", "debug_port",
|
||||
"debug_init_cmds", "debug_extra_cmds", "debug_server",
|
||||
"debug_init_break", "debug_load_cmd", "debug_load_mode",
|
||||
"debug_svd_path", "monitor_port", "monitor_speed", "monitor_rts",
|
||||
"monitor_dtr"
|
||||
]
|
||||
|
||||
IGNORE_BUILD_OPTIONS = [
|
||||
"test_transport", "test_filter", "test_ignore", "test_port",
|
||||
"test_speed", "debug_port", "debug_init_cmds", "debug_extra_cmds",
|
||||
@ -157,17 +127,6 @@ class EnvironmentProcessor(object):
|
||||
|
||||
REMAPED_OPTIONS = {"framework": "pioframework", "platform": "pioplatform"}
|
||||
|
||||
RENAMED_OPTIONS = {
|
||||
"lib_use": "lib_deps",
|
||||
"lib_force": "lib_deps",
|
||||
"extra_script": "extra_scripts",
|
||||
"monitor_baud": "monitor_speed",
|
||||
"board_mcu": "board_build.mcu",
|
||||
"board_f_cpu": "board_build.f_cpu",
|
||||
"board_f_flash": "board_build.f_flash",
|
||||
"board_flash_mode": "board_build.flash_mode"
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self, # pylint: disable=R0913
|
||||
cmd_ctx,
|
||||
@ -201,7 +160,6 @@ class EnvironmentProcessor(object):
|
||||
self.name, fg="cyan", bold=True), "; ".join(env_dump)))
|
||||
click.secho("-" * terminal_width, bold=True)
|
||||
|
||||
self.options = self._validate_options(self.options)
|
||||
result = self._run()
|
||||
is_error = result['returncode'] != 0
|
||||
|
||||
@ -218,31 +176,6 @@ class EnvironmentProcessor(object):
|
||||
|
||||
return not is_error
|
||||
|
||||
def _validate_options(self, options):
|
||||
result = {}
|
||||
for k, v in options.items():
|
||||
# process obsolete options
|
||||
if k in self.RENAMED_OPTIONS:
|
||||
click.secho(
|
||||
"Warning! `%s` option is deprecated and will be "
|
||||
"removed in the next release! Please use "
|
||||
"`%s` instead." % (k, self.RENAMED_OPTIONS[k]),
|
||||
fg="yellow")
|
||||
k = self.RENAMED_OPTIONS[k]
|
||||
|
||||
# warn about unknown options
|
||||
unknown_conditions = [
|
||||
k not in self.KNOWN_ENV_OPTIONS, not k.startswith("custom_"),
|
||||
not k.startswith("board_")
|
||||
]
|
||||
if all(unknown_conditions):
|
||||
click.secho(
|
||||
"Detected non-PlatformIO `%s` option in `[env:%s]` section"
|
||||
% (k, self.name),
|
||||
fg="yellow")
|
||||
result[k] = v
|
||||
return result
|
||||
|
||||
def get_build_variables(self):
|
||||
variables = {"pioenv": self.name}
|
||||
if self.upload_port:
|
||||
@ -381,21 +314,7 @@ def print_summary(results, start_time):
|
||||
is_error=not successed)
|
||||
|
||||
|
||||
def check_project_defopts(config):
|
||||
if not config.has_section("platformio"):
|
||||
return True
|
||||
unknown = set(k for k, _ in config.items("platformio")) - set(
|
||||
EnvironmentProcessor.KNOWN_PLATFORMIO_OPTIONS)
|
||||
if not unknown:
|
||||
return True
|
||||
click.secho(
|
||||
"Warning! Ignore unknown `%s` option in `[platformio]` section" %
|
||||
", ".join(unknown),
|
||||
fg="yellow")
|
||||
return False
|
||||
|
||||
|
||||
def check_project_envs(config, environments=None):
|
||||
def check_project_envs(config, environments=None): # FIXME: Remove
|
||||
if not config.sections():
|
||||
raise exception.ProjectEnvsNotAvailable()
|
||||
|
||||
|
@ -42,11 +42,16 @@ class UserSideException(PlatformioException):
|
||||
pass
|
||||
|
||||
|
||||
class AbortedByUser(PlatformioException):
|
||||
class AbortedByUser(UserSideException):
|
||||
|
||||
MESSAGE = "Aborted by user"
|
||||
|
||||
|
||||
#
|
||||
# Development Platform
|
||||
#
|
||||
|
||||
|
||||
class UnknownPlatform(PlatformioException):
|
||||
|
||||
MESSAGE = "Unknown development platform '{0}'"
|
||||
@ -85,54 +90,75 @@ class UnknownFramework(PlatformioException):
|
||||
MESSAGE = "Unknown framework '{0}'"
|
||||
|
||||
|
||||
class UnknownPackage(PlatformioException):
|
||||
# Package Manager
|
||||
|
||||
|
||||
class PlatformIOPackageException(PlatformioException):
|
||||
pass
|
||||
|
||||
|
||||
class UnknownPackage(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = "Detected unknown package '{0}'"
|
||||
|
||||
|
||||
class MissingPackageManifest(PlatformioException):
|
||||
class MissingPackageManifest(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = "Could not find one of '{0}' manifest files in the package"
|
||||
|
||||
|
||||
class UndefinedPackageVersion(PlatformioException):
|
||||
class UndefinedPackageVersion(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = ("Could not find a version that satisfies the requirement '{0}'"
|
||||
" for your system '{1}'")
|
||||
|
||||
|
||||
class PackageInstallError(PlatformioException):
|
||||
class PackageInstallError(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = ("Could not install '{0}' with version requirements '{1}' "
|
||||
"for your system '{2}'.\n\n"
|
||||
"Please try this solution -> http://bit.ly/faq-package-manager")
|
||||
|
||||
|
||||
class ExtractArchiveItemError(PlatformioException):
|
||||
class ExtractArchiveItemError(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = (
|
||||
"Could not extract `{0}` to `{1}`. Try to disable antivirus "
|
||||
"tool or check this solution -> http://bit.ly/faq-package-manager")
|
||||
|
||||
|
||||
class FDUnrecognizedStatusCode(PlatformioException):
|
||||
class UnsupportedArchiveType(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = "Can not unpack file '{0}'"
|
||||
|
||||
|
||||
class FDUnrecognizedStatusCode(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = "Got an unrecognized status code '{0}' when downloaded {1}"
|
||||
|
||||
|
||||
class FDSizeMismatch(PlatformioException):
|
||||
class FDSizeMismatch(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = ("The size ({0:d} bytes) of downloaded file '{1}' "
|
||||
"is not equal to remote size ({2:d} bytes)")
|
||||
|
||||
|
||||
class FDSHASumMismatch(PlatformioException):
|
||||
class FDSHASumMismatch(PlatformIOPackageException):
|
||||
|
||||
MESSAGE = ("The 'sha1' sum '{0}' of downloaded file '{1}' "
|
||||
"is not equal to remote '{2}'")
|
||||
|
||||
|
||||
class NotPlatformIOProject(PlatformioException):
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
|
||||
class PlatformIOProjectException(PlatformioException):
|
||||
pass
|
||||
|
||||
|
||||
class NotPlatformIOProject(PlatformIOProjectException):
|
||||
|
||||
MESSAGE = (
|
||||
"Not a PlatformIO project. `platformio.ini` file has not been "
|
||||
@ -140,26 +166,82 @@ class NotPlatformIOProject(PlatformioException):
|
||||
"please use `platformio init` command")
|
||||
|
||||
|
||||
class UndefinedEnvPlatform(PlatformioException):
|
||||
class InvalidProjectConf(PlatformIOProjectException):
|
||||
|
||||
MESSAGE = ("Invalid '{0}' (project configuration file): '{1}'")
|
||||
|
||||
|
||||
class UndefinedEnvPlatform(PlatformIOProjectException):
|
||||
|
||||
MESSAGE = "Please specify platform for '{0}' environment"
|
||||
|
||||
|
||||
class UnsupportedArchiveType(PlatformioException):
|
||||
|
||||
MESSAGE = "Can not unpack file '{0}'"
|
||||
|
||||
|
||||
class ProjectEnvsNotAvailable(PlatformioException):
|
||||
class ProjectEnvsNotAvailable(PlatformIOProjectException):
|
||||
|
||||
MESSAGE = "Please setup environments in `platformio.ini` file"
|
||||
|
||||
|
||||
class UnknownEnvNames(PlatformioException):
|
||||
class UnknownEnvNames(PlatformIOProjectException): # FIXME: UnknownProjectEnvs
|
||||
|
||||
MESSAGE = "Unknown environment names '{0}'. Valid names are '{1}'"
|
||||
|
||||
|
||||
#
|
||||
# Library
|
||||
#
|
||||
|
||||
|
||||
class LibNotFound(PlatformioException):
|
||||
|
||||
MESSAGE = ("Library `{0}` has not been found in PlatformIO Registry.\n"
|
||||
"You can ignore this message, if `{0}` is a built-in library "
|
||||
"(included in framework, SDK). E.g., SPI, Wire, etc.")
|
||||
|
||||
|
||||
class NotGlobalLibDir(UserSideException):
|
||||
|
||||
MESSAGE = (
|
||||
"The `{0}` is not a PlatformIO project.\n\n"
|
||||
"To manage libraries in global storage `{1}`,\n"
|
||||
"please use `platformio lib --global {2}` or specify custom storage "
|
||||
"`platformio lib --storage-dir /path/to/storage/ {2}`.\n"
|
||||
"Check `platformio lib --help` for details.")
|
||||
|
||||
|
||||
class InvalidLibConfURL(PlatformioException):
|
||||
|
||||
MESSAGE = "Invalid library config URL '{0}'"
|
||||
|
||||
|
||||
#
|
||||
# UDEV Rules
|
||||
#
|
||||
|
||||
|
||||
class InvalidUdevRules(PlatformioException):
|
||||
pass
|
||||
|
||||
|
||||
class MissedUdevRules(InvalidUdevRules):
|
||||
|
||||
MESSAGE = (
|
||||
"Warning! Please install `99-platformio-udev.rules`. \nMode details: "
|
||||
"https://docs.platformio.org/en/latest/faq.html#platformio-udev-rules")
|
||||
|
||||
|
||||
class OutdatedUdevRules(InvalidUdevRules):
|
||||
|
||||
MESSAGE = (
|
||||
"Warning! Your `{0}` are outdated. Please update or reinstall them."
|
||||
"\n Mode details: https://docs.platformio.org"
|
||||
"/en/latest/faq.html#platformio-udev-rules")
|
||||
|
||||
|
||||
#
|
||||
# Misc
|
||||
#
|
||||
|
||||
|
||||
class GetSerialPortsError(PlatformioException):
|
||||
|
||||
MESSAGE = "No implementation for your platform ('{0}') available"
|
||||
@ -175,7 +257,7 @@ class APIRequestError(PlatformioException):
|
||||
MESSAGE = "[API] {0}"
|
||||
|
||||
|
||||
class InternetIsOffline(PlatformioException):
|
||||
class InternetIsOffline(UserSideException):
|
||||
|
||||
MESSAGE = (
|
||||
"You are not connected to the Internet.\n"
|
||||
@ -183,33 +265,6 @@ class InternetIsOffline(PlatformioException):
|
||||
"to install all dependencies and toolchains.")
|
||||
|
||||
|
||||
class LibNotFound(PlatformioException):
|
||||
|
||||
MESSAGE = ("Library `{0}` has not been found in PlatformIO Registry.\n"
|
||||
"You can ignore this message, if `{0}` is a built-in library "
|
||||
"(included in framework, SDK). E.g., SPI, Wire, etc.")
|
||||
|
||||
|
||||
class NotGlobalLibDir(PlatformioException):
|
||||
|
||||
MESSAGE = (
|
||||
"The `{0}` is not a PlatformIO project.\n\n"
|
||||
"To manage libraries in global storage `{1}`,\n"
|
||||
"please use `platformio lib --global {2}` or specify custom storage "
|
||||
"`platformio lib --storage-dir /path/to/storage/ {2}`.\n"
|
||||
"Check `platformio lib --help` for details.")
|
||||
|
||||
|
||||
class InvalidLibConfURL(PlatformioException):
|
||||
|
||||
MESSAGE = "Invalid library config URL '{0}'"
|
||||
|
||||
|
||||
class InvalidProjectConf(PlatformioException):
|
||||
|
||||
MESSAGE = ("Invalid '{0}' (project configuration file): '{1}'")
|
||||
|
||||
|
||||
class BuildScriptNotFound(PlatformioException):
|
||||
|
||||
MESSAGE = "Invalid path '{0}' to build script"
|
||||
@ -237,25 +292,6 @@ class CIBuildEnvsEmpty(PlatformioException):
|
||||
"predefined environments using `--project-conf` option")
|
||||
|
||||
|
||||
class InvalidUdevRules(PlatformioException):
|
||||
pass
|
||||
|
||||
|
||||
class MissedUdevRules(InvalidUdevRules):
|
||||
|
||||
MESSAGE = (
|
||||
"Warning! Please install `99-platformio-udev.rules`. \nMode details: "
|
||||
"https://docs.platformio.org/en/latest/faq.html#platformio-udev-rules")
|
||||
|
||||
|
||||
class OutdatedUdevRules(InvalidUdevRules):
|
||||
|
||||
MESSAGE = (
|
||||
"Warning! Your `{0}` are outdated. Please update or reinstall them."
|
||||
"\n Mode details: https://docs.platformio.org"
|
||||
"/en/latest/faq.html#platformio-udev-rules")
|
||||
|
||||
|
||||
class UpgradeError(PlatformioException):
|
||||
|
||||
MESSAGE = """{0}
|
||||
@ -290,5 +326,4 @@ class DebugSupportError(PlatformioException):
|
||||
|
||||
|
||||
class DebugInvalidOptions(PlatformioException):
|
||||
|
||||
pass
|
||||
|
@ -23,6 +23,7 @@ from click.testing import CliRunner
|
||||
|
||||
from platformio import exception, util
|
||||
from platformio.commands.run import cli as cmd_run
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
|
||||
class ProjectGenerator(object):
|
||||
@ -44,14 +45,13 @@ class ProjectGenerator(object):
|
||||
@util.memoized()
|
||||
def get_project_env(self):
|
||||
data = {}
|
||||
config = util.load_project_config(self.project_dir)
|
||||
for section in config.sections():
|
||||
if not section.startswith("env:"):
|
||||
config = ProjectConfig.get_instance(
|
||||
join(self.project_dir, "platformio.ini"))
|
||||
for env in config.envs():
|
||||
if self.env_name != env:
|
||||
continue
|
||||
if self.env_name != section[4:]:
|
||||
continue
|
||||
data = {"env_name": section[4:]}
|
||||
for k, v in config.items(section):
|
||||
data = {"env_name": self.env_name}
|
||||
for k, v in config.items(env=env):
|
||||
data[k] = v
|
||||
return data
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
from os.path import isfile
|
||||
|
||||
import click
|
||||
|
||||
@ -25,11 +26,99 @@ try:
|
||||
except ImportError:
|
||||
import configparser as ConfigParser
|
||||
|
||||
KNOWN_PLATFORMIO_OPTIONS = [
|
||||
"description",
|
||||
"env_default",
|
||||
"extra_configs",
|
||||
|
||||
# Dirs
|
||||
"home_dir",
|
||||
"lib_dir",
|
||||
"libdeps_dir",
|
||||
"include_dir",
|
||||
"src_dir",
|
||||
"build_dir",
|
||||
"data_dir",
|
||||
"test_dir",
|
||||
"boards_dir",
|
||||
"lib_extra_dirs"
|
||||
]
|
||||
|
||||
KNOWN_ENV_OPTIONS = [
|
||||
# Generic
|
||||
"platform",
|
||||
"framework",
|
||||
"board",
|
||||
"targets",
|
||||
|
||||
# Build
|
||||
"build_flags",
|
||||
"src_build_flags",
|
||||
"build_unflags",
|
||||
"src_filter",
|
||||
|
||||
# Upload
|
||||
"upload_port",
|
||||
"upload_protocol",
|
||||
"upload_speed",
|
||||
"upload_flags",
|
||||
"upload_resetmethod",
|
||||
|
||||
# Monitor
|
||||
"monitor_port",
|
||||
"monitor_speed",
|
||||
"monitor_rts",
|
||||
"monitor_dtr",
|
||||
|
||||
# Library
|
||||
"lib_deps",
|
||||
"lib_ignore",
|
||||
"lib_extra_dirs",
|
||||
"lib_ldf_mode",
|
||||
"lib_compat_mode",
|
||||
"lib_archive",
|
||||
|
||||
# Test
|
||||
"piotest",
|
||||
"test_filter",
|
||||
"test_ignore",
|
||||
"test_port",
|
||||
"test_speed",
|
||||
"test_transport",
|
||||
"test_build_project_src",
|
||||
|
||||
# Debug
|
||||
"debug_tool",
|
||||
"debug_init_break",
|
||||
"debug_init_cmds",
|
||||
"debug_extra_cmds",
|
||||
"debug_load_cmd",
|
||||
"debug_load_mode",
|
||||
"debug_server",
|
||||
"debug_port",
|
||||
"debug_svd_path",
|
||||
|
||||
# Other
|
||||
"extra_scripts"
|
||||
]
|
||||
|
||||
RENAMED_OPTIONS = {
|
||||
"lib_use": "lib_deps",
|
||||
"lib_force": "lib_deps",
|
||||
"extra_script": "extra_scripts",
|
||||
"monitor_baud": "monitor_speed",
|
||||
"board_mcu": "board_build.mcu",
|
||||
"board_f_cpu": "board_build.f_cpu",
|
||||
"board_f_flash": "board_build.f_flash",
|
||||
"board_flash_mode": "board_build.flash_mode"
|
||||
}
|
||||
|
||||
|
||||
class ProjectConfig(object):
|
||||
|
||||
VARTPL_RE = re.compile(r"\$\{([^\.\}]+)\.([^\}]+)\}")
|
||||
|
||||
_instances = {}
|
||||
_parser = None
|
||||
_parsed = []
|
||||
|
||||
@ -49,13 +138,30 @@ class ProjectConfig(object):
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
def __init__(self, path):
|
||||
@staticmethod
|
||||
def get_instance(path):
|
||||
if not isfile(path):
|
||||
raise exception.NotPlatformIOProject(path)
|
||||
if path not in ProjectConfig._instances:
|
||||
ProjectConfig._instances[path] = ProjectConfig(path)
|
||||
return ProjectConfig._instances[path]
|
||||
|
||||
@staticmethod
|
||||
def reset_instances():
|
||||
ProjectConfig._instances = {}
|
||||
|
||||
def __init__(self, path, parse_extra=True):
|
||||
if not isfile(path):
|
||||
raise exception.NotPlatformIOProject(path)
|
||||
self.path = path
|
||||
self._parsed = []
|
||||
self._parser = ConfigParser.ConfigParser()
|
||||
self.read(path)
|
||||
self.read(path, parse_extra)
|
||||
|
||||
def read(self, path):
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._parser, name)
|
||||
|
||||
def read(self, path, parse_extra=True):
|
||||
if path in self._parsed:
|
||||
return
|
||||
self._parsed.append(path)
|
||||
@ -64,6 +170,9 @@ class ProjectConfig(object):
|
||||
except ConfigParser.Error as e:
|
||||
raise exception.InvalidProjectConf(path, str(e))
|
||||
|
||||
if not parse_extra:
|
||||
return
|
||||
|
||||
# load extra configs
|
||||
if (not self._parser.has_section("platformio")
|
||||
or not self._parser.has_option("platformio", "extra_configs")):
|
||||
@ -74,14 +183,18 @@ class ProjectConfig(object):
|
||||
for item in glob.glob(pattern):
|
||||
self.read(item)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._parser, name)
|
||||
def options(self, section=None, env=None):
|
||||
assert section or env
|
||||
if not section:
|
||||
section = "env:" + env
|
||||
return self._parser.options(section)
|
||||
|
||||
def items(self, section):
|
||||
items = []
|
||||
for option in self._parser.options(section):
|
||||
items.append((option, self.get(section, option)))
|
||||
return items
|
||||
def items(self, section=None, env=None):
|
||||
assert section or env
|
||||
if not section:
|
||||
section = "env:" + env
|
||||
return [(option, self.get(section, option))
|
||||
for option in self.options(section)]
|
||||
|
||||
def get(self, section, option):
|
||||
try:
|
||||
@ -95,7 +208,7 @@ class ProjectConfig(object):
|
||||
def _re_sub_handler(self, match):
|
||||
section, option = match.group(1), match.group(2)
|
||||
if section in ("env",
|
||||
"sysenv") and not self.has_section(section):
|
||||
"sysenv") and not self._parser.has_section(section):
|
||||
if section == "env":
|
||||
click.secho(
|
||||
"Warning! Access to system environment variable via "
|
||||
@ -104,3 +217,67 @@ class ProjectConfig(object):
|
||||
fg="yellow")
|
||||
return os.getenv(option)
|
||||
return self.get(section, option)
|
||||
|
||||
def envs(self):
|
||||
return [s[4:] for s in self._parser.sections() if s.startswith("env:")]
|
||||
|
||||
def default_envs(self):
|
||||
if not self._parser.has_option("platformio", "env_default"):
|
||||
return []
|
||||
return self.parse_multi_values(self.get("platformio", "env_default"))
|
||||
|
||||
def validate(self, envs=None):
|
||||
# check envs
|
||||
known = set(self.envs())
|
||||
if not known:
|
||||
raise exception.ProjectEnvsNotAvailable()
|
||||
|
||||
unknown = set((envs or []) + self.default_envs()) - known
|
||||
if unknown:
|
||||
raise exception.UnknownEnvNames(", ".join(unknown),
|
||||
", ".join(known))
|
||||
return self.validate_options()
|
||||
|
||||
def validate_options(self):
|
||||
warnings = set()
|
||||
# check [platformio] section
|
||||
if self._parser.has_section("platformio"):
|
||||
unknown = set(k for k, _ in self.items("platformio")) - set(
|
||||
KNOWN_PLATFORMIO_OPTIONS)
|
||||
if unknown:
|
||||
warnings.add(
|
||||
"Ignore unknown `%s` options in `[platformio]` section" %
|
||||
", ".join(unknown))
|
||||
|
||||
# check [env:*] sections
|
||||
for section in self._parser.sections():
|
||||
if not section.startswith("env:"):
|
||||
continue
|
||||
for option in self._parser.options(section):
|
||||
# obsolete
|
||||
if option in RENAMED_OPTIONS:
|
||||
warnings.add(
|
||||
"`%s` option in `[%s]` section is deprecated and will "
|
||||
"be removed in the next release! Please use `%s` "
|
||||
"instead" % (option, section, RENAMED_OPTIONS[option]))
|
||||
# rename on-the-fly
|
||||
self._parser.set(section, RENAMED_OPTIONS[option],
|
||||
self._parser.get(section, option))
|
||||
self._parser.remove_option(section, option)
|
||||
continue
|
||||
|
||||
# unknown
|
||||
unknown_conditions = [
|
||||
option not in KNOWN_ENV_OPTIONS,
|
||||
not option.startswith("custom_"),
|
||||
not option.startswith("board_")
|
||||
] # yapf: disable
|
||||
if all(unknown_conditions):
|
||||
warnings.add(
|
||||
"Detected non-PlatformIO `%s` option in `[%s]` section"
|
||||
% (option, section))
|
||||
|
||||
for warning in warnings:
|
||||
click.secho("Warning! %s" % warning, fg="yellow")
|
||||
|
||||
return True
|
||||
|
@ -342,12 +342,9 @@ def on_exception(e):
|
||||
return text.strip()
|
||||
|
||||
skip_conditions = [
|
||||
isinstance(e, cls)
|
||||
for cls in (IOError, exception.ReturnErrorCode,
|
||||
exception.AbortedByUser, exception.NotGlobalLibDir,
|
||||
exception.InternetIsOffline,
|
||||
exception.NotPlatformIOProject,
|
||||
exception.UserSideException)
|
||||
isinstance(e, cls) for cls in (IOError, exception.ReturnErrorCode,
|
||||
exception.UserSideException,
|
||||
exception.PlatformIOProjectException)
|
||||
]
|
||||
try:
|
||||
skip_conditions.append("[API] Account: " in str(e))
|
||||
|
@ -180,7 +180,8 @@ def get_project_optional_dir(name, default=None):
|
||||
paths = os.getenv(var_name)
|
||||
else:
|
||||
try:
|
||||
config = load_project_config()
|
||||
config = ProjectConfig.get_instance(
|
||||
join(get_project_dir(), "platformio.ini"))
|
||||
if (config.has_section("platformio")
|
||||
and config.has_option("platformio", name)):
|
||||
paths = config.get("platformio", name)
|
||||
@ -312,7 +313,7 @@ def get_projectdata_dir():
|
||||
"data"))
|
||||
|
||||
|
||||
def load_project_config(path=None): # FIXME:
|
||||
def load_project_config(path=None): # FIXME: Remove
|
||||
if not path or isdir(path):
|
||||
path = join(path or get_project_dir(), "platformio.ini")
|
||||
if not isfile(path):
|
||||
@ -321,7 +322,7 @@ def load_project_config(path=None): # FIXME:
|
||||
return ProjectConfig(path)
|
||||
|
||||
|
||||
def parse_conf_multi_values(items): # FIXME:
|
||||
def parse_conf_multi_values(items): # FIXME: Remove
|
||||
return ProjectConfig.parse_multi_values(items)
|
||||
|
||||
|
||||
|
@ -24,8 +24,10 @@ from platformio import util
|
||||
def validate_cliresult():
|
||||
|
||||
def decorator(result):
|
||||
assert result.exit_code == 0, result.output
|
||||
assert not result.exception, result.output
|
||||
assert result.exit_code == 0, "{} => {}".format(
|
||||
result.exception, result.output)
|
||||
assert not result.exception, "{} => {}".format(result.exception,
|
||||
result.output)
|
||||
|
||||
return decorator
|
||||
|
||||
|
@ -13,10 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
BASE_CONFIG = """
|
||||
[platformio]
|
||||
env_default = esp32dev, lolin32
|
||||
extra_configs =
|
||||
extra_envs.ini
|
||||
extra_debug.ini
|
||||
@ -86,8 +88,15 @@ def test_parser(tmpdir):
|
||||
"build_flags") == ("-D DEBUG=1 -L /usr/local/lib")
|
||||
|
||||
# items
|
||||
assert config.items("env:esp32dev") == [("platform", "espressif32"),
|
||||
assert config.items("common") == [("debug_flags", "-D DEBUG=1"),
|
||||
("lib_flags", "-lc -lm"),
|
||||
("extra_flags", "-L /usr/local/lib")]
|
||||
assert config.items(env="esp32dev") == [("platform", "espressif32"),
|
||||
("framework", "espidf"),
|
||||
("board", "esp32dev"),
|
||||
("build_flags",
|
||||
"-lc -lm -D DEBUG=1")]
|
||||
|
||||
# envs
|
||||
assert config.envs() == ["esp-wrover-kit", "esp32dev", "lolin32"]
|
||||
assert config.default_envs() == ["esp32dev", "lolin32"]
|
||||
|
Reference in New Issue
Block a user