예제 #1
0
def init_base_project(project_dir):
    with fs.cd(project_dir):
        config = ProjectConfig()
        config.save()
        dir_to_readme = [
            (config.get_optional_dir("src"), None),
            (config.get_optional_dir("include"), init_include_readme),
            (config.get_optional_dir("lib"), init_lib_readme),
            (config.get_optional_dir("test"), init_test_readme),
        ]
        for (path, cb) in dir_to_readme:
            if os.path.isdir(path):
                continue
            os.makedirs(path)
            if cb:
                cb(path)
예제 #2
0
def cli(ctx, **options):
    storage_cmds = ("install", "uninstall", "update", "list")
    # skip commands that don't need storage folder
    if ctx.invoked_subcommand not in storage_cmds or (
        len(ctx.args) == 2 and ctx.args[1] in ("-h", "--help")
    ):
        return
    storage_dirs = list(options["storage_dir"])
    if options["global"]:
        storage_dirs.append(get_project_global_lib_dir())
    if not storage_dirs:
        if is_platformio_project():
            storage_dirs = [get_project_dir()]
        elif is_ci():
            storage_dirs = [get_project_global_lib_dir()]
            click.secho(
                "Warning! Global library storage is used automatically. "
                "Please use `platformio lib --global %s` command to remove "
                "this warning." % ctx.invoked_subcommand,
                fg="yellow",
            )

    if not storage_dirs:
        raise NotGlobalLibDir(
            get_project_dir(), get_project_global_lib_dir(), ctx.invoked_subcommand
        )

    in_silence = PlatformioCLI.in_silence()
    ctx.meta[CTX_META_PROJECT_ENVIRONMENTS_KEY] = options["environment"]
    ctx.meta[CTX_META_INPUT_DIRS_KEY] = storage_dirs
    ctx.meta[CTX_META_STORAGE_DIRS_KEY] = []
    ctx.meta[CTX_META_STORAGE_LIBDEPS_KEY] = {}
    for storage_dir in storage_dirs:
        if not is_platformio_project(storage_dir):
            ctx.meta[CTX_META_STORAGE_DIRS_KEY].append(storage_dir)
            continue
        with fs.cd(storage_dir):
            config = ProjectConfig.get_instance(
                os.path.join(storage_dir, "platformio.ini")
            )
            config.validate(options["environment"], silent=in_silence)
            libdeps_dir = config.get_optional_dir("libdeps")
            for env in config.envs():
                if options["environment"] and env not in options["environment"]:
                    continue
                storage_dir = os.path.join(libdeps_dir, env)
                ctx.meta[CTX_META_STORAGE_DIRS_KEY].append(storage_dir)
                ctx.meta[CTX_META_STORAGE_LIBDEPS_KEY][storage_dir] = config.get(
                    "env:" + env, "lib_deps", []
                )
예제 #3
0
    def __init__(self, options=None):
        """ Called by PlatformIO to pass context """
        miniterm.Transform.__init__(self)

        self.options = options or {}
        self.project_dir = self.options.get("project_dir")
        self.environment = self.options.get("environment")

        self.config = ProjectConfig.get_instance()
        if not self.environment:
            default_envs = self.config.default_envs()
            if default_envs:
                self.environment = default_envs[0]
            elif self.config.envs():
                self.environment = self.config.envs()[0]
예제 #4
0
    def add_project_items(self, psync):
        with util.cd(self.options["project_dir"]):
            cfg = ProjectConfig.get_instance(
                os.path.join(self.options["project_dir"], "platformio.ini"))
            psync.add_item(cfg.path, "platformio.ini")
            psync.add_item(cfg.get_optional_dir("shared"), "shared")
            psync.add_item(cfg.get_optional_dir("boards"), "boards")

            if self.options["force_remote"]:
                self._add_project_source_items(cfg, psync)
            else:
                self._add_project_binary_items(cfg, psync)

            if self.command == "test":
                psync.add_item(cfg.get_optional_dir("test"), "test")
예제 #5
0
def init_base_project(project_dir):
    ProjectConfig(join(project_dir, "platformio.ini")).save()
    with fs.cd(project_dir):
        dir_to_readme = [
            (get_project_src_dir(), None),
            (get_project_include_dir(), init_include_readme),
            (get_project_lib_dir(), init_lib_readme),
            (get_project_test_dir(), init_test_readme),
        ]
        for (path, cb) in dir_to_readme:
            if isdir(path):
                continue
            makedirs(path)
            if cb:
                cb(path)
예제 #6
0
    def get_project_examples():
        result = []
        for manifest in PlatformManager().get_installed():
            examples_dir = os.path.join(manifest["__pkg_dir"], "examples")
            if not os.path.isdir(examples_dir):
                continue
            items = []
            for project_dir, _, __ in os.walk(examples_dir):
                project_description = None
                try:
                    config = ProjectConfig(
                        os.path.join(project_dir, "platformio.ini"))
                    config.validate(silent=True)
                    project_description = config.get("platformio",
                                                     "description")
                except ProjectError:
                    continue

                path_tokens = project_dir.split(os.path.sep)
                items.append({
                    "name":
                    "/".join(path_tokens[path_tokens.index("examples") + 1:]),
                    "path":
                    project_dir,
                    "description":
                    project_description,
                })
            result.append({
                "platform": {
                    "title": manifest["title"],
                    "version": manifest["version"],
                },
                "items":
                sorted(items, key=lambda item: item["name"]),
            })
        return sorted(result, key=lambda data: data["platform"]["title"])
예제 #7
0
    def __init__(self, manifest_path):
        self.manifest_path = manifest_path
        self.silent = False
        self.verbose = False

        self._manifest = fs.load_json(manifest_path)
        self._BOARDS_CACHE = {}
        self._custom_packages = None

        self.config = ProjectConfig.get_instance()
        self.pm = PackageManager(self.config.get_optional_dir("packages"),
                                 self.package_repositories)

        self._src_manifest = None
        src_manifest_path = self.pm.get_src_manifest_path(self.get_dir())
        if src_manifest_path:
            self._src_manifest = fs.load_json(src_manifest_path)
예제 #8
0
def get_project_optional_dir(name, default=None):
    project_dir = get_project_dir()
    config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
    optional_dir = config.get("platformio", name)

    if not optional_dir:
        return default

    if "$PROJECT_HASH" in optional_dir:
        optional_dir = optional_dir.replace(
            "$PROJECT_HASH", "%s-%s" %
            (basename(project_dir), sha1(
                hashlib_encode_data(project_dir)).hexdigest()[:10]))

    if optional_dir.startswith("~"):
        optional_dir = expanduser(optional_dir)

    return realpath(optional_dir)
def load_config():
    items = ProjectConfig().items('features')
    for key in items:
        feature = key[0].upper()
        if not feature in FEATURE_CONFIG:
            FEATURE_CONFIG[feature] = {'lib_deps': []}
        add_to_feat_cnf(feature, key[1])

    # Add options matching custom_marlin.MY_OPTION to the pile
    all_opts = env.GetProjectOptions()
    for n in all_opts:
        mat = re.match(r'custom_marlin\.(.+)', n[0])
        if mat:
            try:
                val = env.GetProjectOption(n[0])
            except:
                val = None
            if val:
                add_to_feat_cnf(mat.group(1).upper(), val)
예제 #10
0
def test_init_custom_framework(clirunner, validate_cliresult):
    with clirunner.isolated_filesystem():
        result = clirunner.invoke(
            cmd_init, ["-b", "teensy31", "--project-option", "framework=mbed"])
        validate_cliresult(result)
        validate_pioproject(getcwd())
        config = ProjectConfig(join(getcwd(), "platformio.ini"))
        config.validate()
        expected_result = dict(platform="teensy",
                               board="teensy31",
                               framework=["mbed"])
        assert config.has_section("env:teensy31")
        assert sorted(config.items(env="teensy31",
                                   as_dict=True).items()) == sorted(
                                       expected_result.items())
예제 #11
0
def test_init_enable_auto_uploading(clirunner, validate_cliresult):
    with clirunner.isolated_filesystem():
        result = clirunner.invoke(
            cmd_init, ["-b", "uno", "--project-option", "targets=upload"])
        validate_cliresult(result)
        validate_pioproject(getcwd())
        config = ProjectConfig(join(getcwd(), "platformio.ini"))
        config.validate()
        expected_result = dict(targets=["upload"],
                               platform="atmelavr",
                               board="uno",
                               framework=["arduino"])
        assert config.has_section("env:uno")
        assert sorted(config.items(env="uno", as_dict=True).items()) == sorted(
            expected_result.items())
예제 #12
0
def test_update_and_clear(tmpdir_factory):
    tmpdir = tmpdir_factory.mktemp("project")
    tmpdir.join("platformio.ini").write("""
[platformio]
extra_configs = a.ini, b.ini

[env:myenv]
board = myboard
    """)
    config = ProjectConfig(tmpdir.join("platformio.ini").strpath)
    assert config.sections() == ["platformio", "env:myenv"]
    config.update([["mysection", [("opt1", "value1"), ("opt2", "value2")]]],
                  clear=True)
    assert config.as_tuple() == [("mysection", [("opt1", "value1"),
                                                ("opt2", "value2")])]
예제 #13
0
def save_project_libdeps(project_dir, specs, environments=None, action="add"):
    config = ProjectConfig.get_instance(
        os.path.join(project_dir, "platformio.ini"))
    config.validate(environments)
    for env in config.envs():
        if environments and env not in environments:
            continue
        config.expand_interpolations = False
        lib_deps = []
        try:
            lib_deps = ignore_deps_by_specs(
                config.get("env:" + env, "lib_deps"), specs)
        except InvalidProjectConfError:
            pass
        if action == "add":
            lib_deps.extend(spec.as_dependency() for spec in specs)
        if lib_deps:
            config.set("env:" + env, "lib_deps", lib_deps)
        elif config.has_option("env:" + env, "lib_deps"):
            config.remove_option("env:" + env, "lib_deps")
    config.save()
예제 #14
0
def project_config(project_dir, json_output):
    if not is_platformio_project(project_dir):
        raise NotPlatformIOProjectError(project_dir)
    with fs.cd(project_dir):
        config = ProjectConfig.get_instance()
    if json_output:
        return click.echo(config.to_json())
    click.echo("Computed project configuration for %s" %
               click.style(project_dir, fg="cyan"))
    for section, options in config.as_tuple():
        click.secho(section, fg="cyan")
        click.echo("-" * len(section))
        click.echo(
            tabulate(
                [(name, "=",
                  "\n".join(value) if isinstance(value, list) else value)
                 for name, value in options],
                tablefmt="plain",
            ))
        click.echo()
    return None
예제 #15
0
def get_best_envname(project_dir, boards=None):
    config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
    config.validate()

    envname = None
    default_envs = config.default_envs()
    if default_envs:
        envname = default_envs[0]
        if not boards:
            return envname

    for env in config.envs():
        if not boards:
            return env
        if not envname:
            envname = env
        items = config.items(env=env, as_dict=True)
        if "board" in items and items.get("board") in boards:
            return env

    return envname
예제 #16
0
    def load_features():
        blab("========== Gather [features] entries...")
        for key in ProjectConfig().items('features'):
            feature = key[0].upper()
            if not feature in FEATURE_CONFIG:
                FEATURE_CONFIG[feature] = {'lib_deps': []}
            add_to_feat_cnf(feature, key[1])

        # Add options matching custom_marlin.MY_OPTION to the pile
        blab("========== Gather custom_marlin entries...")
        for n in env.GetProjectOptions():
            key = n[0]
            mat = re.match(r'custom_marlin\.(.+)', key)
            if mat:
                try:
                    val = env.GetProjectOption(key)
                except:
                    val = None
                if val:
                    opt = mat[1].upper()
                    blab("%s.custom_marlin.%s = '%s'" %
                         (env['PIOENV'], opt, val))
                    add_to_feat_cnf(opt, val)
예제 #17
0
def test_init_special_board(clirunner, validate_cliresult):
    with clirunner.isolated_filesystem():
        result = clirunner.invoke(cmd_init, ["-b", "uno"])
        validate_cliresult(result)
        validate_pioproject(getcwd())

        result = clirunner.invoke(cmd_boards, ["Arduino Uno", "--json-output"])
        validate_cliresult(result)
        boards = json.loads(result.output)

        config = ProjectConfig(join(getcwd(), "platformio.ini"))
        config.validate()

        expected_result = dict(platform=str(boards[0]['platform']),
                               board="uno",
                               framework=[str(boards[0]['frameworks'][0])])
        assert config.has_section("env:uno")
        assert sorted(config.items(env="uno", as_dict=True).items()) == sorted(
            expected_result.items())
예제 #18
0
def cli(ctx, project_dir, project_conf, environment, verbose, interface,
        __unprocessed):
    app.set_session_var("custom_project_conf", project_conf)

    # use env variables from Eclipse or CLion
    for sysenv in ("CWD", "PWD", "PLATFORMIO_PROJECT_DIR"):
        if is_platformio_project(project_dir):
            break
        if os.getenv(sysenv):
            project_dir = os.getenv(sysenv)

    with fs.cd(project_dir):
        config = ProjectConfig.get_instance(project_conf)
        config.validate(envs=[environment] if environment else None)

        env_name = environment or helpers.get_default_debug_env(config)
        env_options = config.items(env=env_name, as_dict=True)
        if not set(env_options.keys()) >= set(["platform", "board"]):
            raise ProjectEnvsNotAvailableError()
        debug_options = helpers.validate_debug_options(ctx, env_options)
        assert debug_options

    if not interface:
        return helpers.predebug_project(ctx, project_dir, env_name, False,
                                        verbose)

    configuration = load_project_ide_data(project_dir, env_name)
    if not configuration:
        raise DebugInvalidOptionsError("Could not load debug configuration")

    if "--version" in __unprocessed:
        result = proc.exec_command([configuration["gdb_path"], "--version"])
        if result["returncode"] == 0:
            return click.echo(result["out"])
        raise exception.PlatformioException("\n".join(
            [result["out"], result["err"]]))

    try:
        fs.ensure_udev_rules()
    except exception.InvalidUdevRules as e:
        click.echo(
            helpers.escape_gdbmi_stream("~",
                                        str(e) + "\n")
            if helpers.is_gdbmi_mode() else str(e) + "\n",
            nl=False,
        )

    debug_options["load_cmds"] = helpers.configure_esp32_load_cmds(
        debug_options, configuration)

    rebuild_prog = False
    preload = debug_options["load_cmds"] == ["preload"]
    load_mode = debug_options["load_mode"]
    if load_mode == "always":
        rebuild_prog = preload or not helpers.has_debug_symbols(
            configuration["prog_path"])
    elif load_mode == "modified":
        rebuild_prog = helpers.is_prog_obsolete(
            configuration["prog_path"]) or not helpers.has_debug_symbols(
                configuration["prog_path"])
    else:
        rebuild_prog = not isfile(configuration["prog_path"])

    if preload or (not rebuild_prog and load_mode != "always"):
        # don't load firmware through debug server
        debug_options["load_cmds"] = []

    if rebuild_prog:
        if helpers.is_gdbmi_mode():
            click.echo(
                helpers.escape_gdbmi_stream(
                    "~", "Preparing firmware for debugging...\n"),
                nl=False,
            )
            stream = helpers.GDBMIConsoleStream()
            with util.capture_std_streams(stream):
                helpers.predebug_project(ctx, project_dir, env_name, preload,
                                         verbose)
            stream.close()
        else:
            click.echo("Preparing firmware for debugging...")
            helpers.predebug_project(ctx, project_dir, env_name, preload,
                                     verbose)

        # save SHA sum of newly created prog
        if load_mode == "modified":
            helpers.is_prog_obsolete(configuration["prog_path"])

    if not isfile(configuration["prog_path"]):
        raise DebugInvalidOptionsError("Program/firmware is missed")

    # run debugging client
    inject_contrib_pysite()

    # pylint: disable=import-outside-toplevel
    from platformio.commands.debug.process.client import GDBClient, reactor

    client = GDBClient(project_dir, __unprocessed, debug_options, env_options)
    client.spawn(configuration["gdb_path"], configuration["prog_path"])

    signal.signal(signal.SIGINT, lambda *args, **kwargs: None)
    reactor.run()

    return True
예제 #19
0
 def config_update_description(path, text):
     config = ProjectConfig(path,
                            parse_extra=False,
                            expand_interpolations=False)
     if not config.has_section("platformio"):
         config.add_section("platformio")
     if text:
         config.set("platformio", "description", text)
     else:
         if config.has_option("platformio", "description"):
             config.remove_option("platformio", "description")
         if not config.options("platformio"):
             config.remove_section("platformio")
     return config.save()
예제 #20
0
 def config_dump(path, data):
     config = ProjectConfig(path,
                            parse_extra=False,
                            expand_interpolations=False)
     config.update(data, clear=True)
     return config.save()
예제 #21
0
 def config_load(path):
     return ProjectConfig(path,
                          parse_extra=False,
                          expand_interpolations=False).as_tuple()
예제 #22
0
def fill_project_envs(ctx, project_dir, board_ids, project_option, env_prefix,
                      force_download):
    config = ProjectConfig(join(project_dir, "platformio.ini"),
                           parse_extra=False)
    used_boards = []
    for section in config.sections():
        cond = [
            section.startswith("env:"),
            config.has_option(section, "board")
        ]
        if all(cond):
            used_boards.append(config.get(section, "board"))

    pm = PlatformManager()
    used_platforms = []
    modified = False
    for id_ in board_ids:
        board_config = pm.board_config(id_)
        used_platforms.append(board_config['platform'])
        if id_ in used_boards:
            continue
        used_boards.append(id_)
        modified = True

        envopts = {"platform": board_config['platform'], "board": id_}
        # find default framework for board
        frameworks = board_config.get("frameworks")
        if frameworks:
            envopts['framework'] = frameworks[0]

        for item in project_option:
            if "=" not in item:
                continue
            _name, _value = item.split("=", 1)
            envopts[_name.strip()] = _value.strip()

        section = "env:%s%s" % (env_prefix, id_)
        config.add_section(section)

        for option, value in envopts.items():
            config.set(section, option, value)

    if force_download and used_platforms:
        _install_dependent_platforms(ctx, used_platforms)

    if modified:
        config.save()
        config.reset_instances()
예제 #23
0
def project_init(
    ctx,  # pylint: disable=R0913
    project_dir,
    board,
    ide,
    environment,
    project_option,
    env_prefix,
    silent,
):
    if not silent:
        if project_dir == os.getcwd():
            click.secho("\nThe current working directory",
                        fg="yellow",
                        nl=False)
            click.secho(" %s " % project_dir, fg="cyan", nl=False)
            click.secho("will be used for the project.", fg="yellow")
            click.echo("")

        click.echo("The next files/directories have been created in %s" %
                   click.style(project_dir, fg="cyan"))
        click.echo("%s - Put project header files here" %
                   click.style("include", fg="cyan"))
        click.echo("%s - Put here project specific (private) libraries" %
                   click.style("lib", fg="cyan"))
        click.echo("%s - Put project source files here" %
                   click.style("src", fg="cyan"))
        click.echo("%s - Project Configuration File" %
                   click.style("platformio.ini", fg="cyan"))

    is_new_project = not is_platformio_project(project_dir)
    if is_new_project:
        init_base_project(project_dir)

    if environment:
        update_project_env(project_dir, environment, project_option)
    elif board:
        update_board_envs(ctx, project_dir, board, project_option, env_prefix,
                          ide is not None)

    if ide:
        with fs.cd(project_dir):
            config = ProjectConfig.get_instance(
                os.path.join(project_dir, "platformio.ini"))
        config.validate()
        pg = ProjectGenerator(config, environment
                              or get_best_envname(config, board), ide)
        pg.generate()

    if is_new_project:
        init_cvs_ignore(project_dir)

    if silent:
        return

    if ide:
        click.secho(
            "\nProject has been successfully %s including configuration files "
            "for `%s` IDE." %
            ("initialized" if is_new_project else "updated", ide),
            fg="green",
        )
    else:
        click.secho(
            "\nProject has been successfully %s! Useful commands:\n"
            "`pio run` - process/build project from the current directory\n"
            "`pio run --target upload` or `pio run -t upload` "
            "- upload firmware to a target\n"
            "`pio run --target clean` - clean project (remove compiled files)"
            "\n`pio run --help` - additional information" %
            ("initialized" if is_new_project else "updated"),
            fg="green",
        )
예제 #24
0
def cli(
    environment,
    project_dir,
    project_conf,
    pattern,
    flags,
    severity,
    silent,
    verbose,
    json_output,
    fail_on_defect,
    skip_packages,
):
    app.set_session_var("custom_project_conf", project_conf)

    # find project directory on upper level
    if isfile(project_dir):
        project_dir = find_project_dir_above(project_dir)

    results = []
    with fs.cd(project_dir):
        config = ProjectConfig.get_instance(project_conf)
        config.validate(environment)

        default_envs = config.default_envs()
        for envname in config.envs():
            skipenv = any([
                environment and envname not in environment,
                not environment and default_envs
                and envname not in default_envs,
            ])

            env_options = config.items(env=envname, as_dict=True)
            env_dump = []
            for k, v in env_options.items():
                if k not in ("platform", "framework", "board"):
                    continue
                env_dump.append(
                    "%s: %s" % (k, ", ".join(v) if isinstance(v, list) else v))

            default_patterns = [
                config.get_optional_dir("src"),
                config.get_optional_dir("include"),
            ]
            tool_options = dict(
                verbose=verbose,
                silent=silent,
                patterns=pattern
                or env_options.get("check_patterns", default_patterns),
                flags=flags or env_options.get("check_flags"),
                severity=[
                    DefectItem.SEVERITY_LABELS[DefectItem.SEVERITY_HIGH]
                ] if silent else severity
                or config.get("env:" + envname, "check_severity"),
                skip_packages=skip_packages
                or env_options.get("check_skip_packages"),
            )

            for tool in config.get("env:" + envname, "check_tool"):
                if skipenv:
                    results.append({"env": envname, "tool": tool})
                    continue
                if not silent and not json_output:
                    print_processing_header(tool, envname, env_dump)

                ct = CheckToolFactory.new(tool, project_dir, config, envname,
                                          tool_options)

                result = {"env": envname, "tool": tool, "duration": time()}
                rc = ct.check(on_defect_callback=None if (
                    json_output or verbose
                ) else lambda defect: click.echo(repr(defect)))

                result["defects"] = ct.get_defects()
                result["duration"] = time() - result["duration"]

                result["succeeded"] = rc == 0
                if fail_on_defect:
                    result["succeeded"] = rc == 0 and not any(
                        DefectItem.SEVERITY_LABELS[
                            d.severity] in fail_on_defect
                        for d in result["defects"])
                result["stats"] = collect_component_stats(result)
                results.append(result)

                if verbose:
                    click.echo("\n".join(repr(d) for d in result["defects"]))

                if not json_output and not silent:
                    if rc != 0:
                        click.echo("Error: %s failed to perform check! Please "
                                   "examine tool output in verbose mode." %
                                   tool)
                    elif not result["defects"]:
                        click.echo("No defects found")
                    print_processing_footer(result)

        if json_output:
            click.echo(dump_json_to_unicode(results_to_json(results)))
        elif not silent:
            print_check_summary(results)

    command_failed = any(r.get("succeeded") is False for r in results)
    if command_failed:
        raise exception.ReturnErrorCode(1)
예제 #25
0
def test_update_and_save(tmpdir_factory):
    tmpdir = tmpdir_factory.mktemp("project")
    tmpdir.join("platformio.ini").write(
        """
[platformio]
extra_configs = a.ini, b.ini

[env:myenv]
board = myboard
    """
    )
    config = ProjectConfig(tmpdir.join("platformio.ini").strpath)
    assert config.envs() == ["myenv"]
    assert config.as_tuple()[0][1][0][1] == ["a.ini", "b.ini"]

    config.update(
        [
            ["platformio", [("extra_configs", ["extra.ini"])]],
            ["env:myenv", [("framework", ["espidf", "arduino"])]],
            ["check_types", [("float_option", 13.99), ("bool_option", True)]],
        ]
    )
    assert config.get("platformio", "extra_configs") == ["extra.ini"]
    config.remove_section("platformio")
    assert config.as_tuple() == [
        ("env:myenv", [("board", "myboard"), ("framework", ["espidf", "arduino"])]),
        ("check_types", [("float_option", "13.99"), ("bool_option", "yes")]),
    ]

    config.save()
    contents = tmpdir.join("platformio.ini").read()
    assert contents[-4:] == "yes\n"
    lines = [
        line.strip()
        for line in contents.split("\n")
        if line.strip() and not line.startswith((";", "#"))
    ]
    assert lines == [
        "[env:myenv]",
        "board = myboard",
        "framework =",
        "espidf",
        "arduino",
        "[check_types]",
        "float_option = 13.99",
        "bool_option = yes",
    ]
예제 #26
0
def cli(ctx, project_dir, project_conf, environment, verbose, interface,
        __unprocessed):
    # use env variables from Eclipse or CLion
    for sysenv in ("CWD", "PWD", "PLATFORMIO_PROJECT_DIR"):
        if is_platformio_project(project_dir):
            break
        if os.getenv(sysenv):
            project_dir = os.getenv(sysenv)

    with util.cd(project_dir):
        config = ProjectConfig.get_instance(
            project_conf or join(project_dir, "platformio.ini"))
        config.validate(envs=[environment] if environment else None)

        env_name = environment or helpers.get_default_debug_env(config)
        env_options = config.items(env=env_name, as_dict=True)
        if not set(env_options.keys()) >= set(["platform", "board"]):
            raise exception.ProjectEnvsNotAvailable()
        debug_options = helpers.validate_debug_options(ctx, env_options)
        assert debug_options

    if not interface:
        return helpers.predebug_project(ctx, project_dir, env_name, False,
                                        verbose)

    configuration = load_project_ide_data(project_dir, env_name)
    if not configuration:
        raise exception.DebugInvalidOptions(
            "Could not load debug configuration")

    if "--version" in __unprocessed:
        result = util.exec_command([configuration['gdb_path'], "--version"])
        if result['returncode'] == 0:
            return click.echo(result['out'])
        raise exception.PlatformioException("\n".join(
            [result['out'], result['err']]))

    try:
        util.ensure_udev_rules()
    except NameError:
        pass
    except exception.InvalidUdevRules as e:
        for line in str(e).split("\n") + [""]:
            click.echo(
                ('~"%s\\n"' if helpers.is_mi_mode(__unprocessed) else "%s") %
                line)

    debug_options['load_cmds'] = helpers.configure_esp32_load_cmds(
        debug_options, configuration)

    rebuild_prog = False
    preload = debug_options['load_cmds'] == ["preload"]
    load_mode = debug_options['load_mode']
    if load_mode == "always":
        rebuild_prog = (
            preload
            or not helpers.has_debug_symbols(configuration['prog_path']))
    elif load_mode == "modified":
        rebuild_prog = (
            helpers.is_prog_obsolete(configuration['prog_path'])
            or not helpers.has_debug_symbols(configuration['prog_path']))
    else:
        rebuild_prog = not isfile(configuration['prog_path'])

    if preload or (not rebuild_prog and load_mode != "always"):
        # don't load firmware through debug server
        debug_options['load_cmds'] = []

    if rebuild_prog:
        if helpers.is_mi_mode(__unprocessed):
            click.echo('~"Preparing firmware for debugging...\\n"')
            output = helpers.GDBBytesIO()
            with util.capture_std_streams(output):
                helpers.predebug_project(ctx, project_dir, env_name, preload,
                                         verbose)
            output.close()
        else:
            click.echo("Preparing firmware for debugging...")
            helpers.predebug_project(ctx, project_dir, env_name, preload,
                                     verbose)

        # save SHA sum of newly created prog
        if load_mode == "modified":
            helpers.is_prog_obsolete(configuration['prog_path'])

    if not isfile(configuration['prog_path']):
        raise exception.DebugInvalidOptions("Program/firmware is missed")

    # run debugging client
    inject_contrib_pysite()
    from platformio.commands.debug.client import GDBClient, reactor

    client = GDBClient(project_dir, __unprocessed, debug_options, env_options)
    client.spawn(configuration['gdb_path'], configuration['prog_path'])

    signal.signal(signal.SIGINT, lambda *args, **kwargs: None)
    reactor.run()

    return True
예제 #27
0
def cli(  # pylint: disable=redefined-builtin
        ctx, environment, ignore, filter, upload_port, test_port, project_dir,
        project_conf, without_building, without_uploading, without_testing,
        no_reset, monitor_rts, monitor_dtr, verbose):
    with fs.cd(project_dir):
        test_dir = get_project_test_dir()
        if not isdir(test_dir):
            raise exception.TestDirNotExists(test_dir)
        test_names = get_test_names(test_dir)

        config = ProjectConfig.get_instance(
            project_conf or join(project_dir, "platformio.ini"))
        config.validate(envs=environment)

        click.echo("Verbose mode can be enabled via `-v, --verbose` option")
        click.secho("Collected %d items" % len(test_names), bold=True)

        results = []
        default_envs = config.default_envs()
        for testname in test_names:

            for envname in config.envs():
                section = "env:%s" % envname

                # filter and ignore patterns
                patterns = dict(filter=list(filter), ignore=list(ignore))
                for key in patterns:
                    patterns[key].extend(
                        config.get(section, "test_%s" % key, []))

                skip_conditions = [
                    environment and envname not in environment,
                    not environment and default_envs
                    and envname not in default_envs,
                    testname != "*" and patterns['filter'] and
                    not any([fnmatch(testname, p)
                             for p in patterns['filter']]),
                    testname != "*"
                    and any([fnmatch(testname, p)
                             for p in patterns['ignore']]),
                ]
                if any(skip_conditions):
                    results.append({"env": envname, "test": testname})
                    continue

                click.echo()
                print_processing_header(testname, envname)

                cls = (NativeTestProcessor if config.get(section, "platform")
                       == "native" else EmbeddedTestProcessor)
                tp = cls(
                    ctx, testname, envname,
                    dict(project_config=config,
                         project_dir=project_dir,
                         upload_port=upload_port,
                         test_port=test_port,
                         without_building=without_building,
                         without_uploading=without_uploading,
                         without_testing=without_testing,
                         no_reset=no_reset,
                         monitor_rts=monitor_rts,
                         monitor_dtr=monitor_dtr,
                         verbose=verbose))
                result = {
                    "env": envname,
                    "test": testname,
                    "duration": time(),
                    "succeeded": tp.process()
                }
                result['duration'] = time() - result['duration']
                results.append(result)

                print_processing_footer(result)

    if without_testing:
        return

    print_testing_summary(results)

    command_failed = any(r.get("succeeded") is False for r in results)
    if command_failed:
        raise exception.ReturnErrorCode(1)
예제 #28
0
 def __init__(self, package_dir=None):
     self.config = ProjectConfig.get_instance()
     super(LibraryManager,
           self).__init__(package_dir
                          or self.config.get_optional_dir("globallib"))
예제 #29
0
    def _process_cmd_run_or_test(  # pylint: disable=too-many-locals,too-many-branches
            self, command, options):
        assert options and "project_id" in options
        project_dir = join(self.working_dir, "projects", options["project_id"])
        origin_pio_ini = join(project_dir, "platformio.ini")
        back_pio_ini = join(project_dir, "platformio.ini.bak")

        # remove insecure project options
        try:
            conf = ProjectConfig(origin_pio_ini)
            if isfile(back_pio_ini):
                os.remove(back_pio_ini)
            os.rename(origin_pio_ini, back_pio_ini)
            # cleanup
            if conf.has_section("platformio"):
                for opt in conf.options("platformio"):
                    if opt.endswith("_dir"):
                        conf.remove_option("platformio", opt)
            else:
                conf.add_section("platformio")
            conf.set("platformio", "build_dir", ".pio/build")
            conf.save(origin_pio_ini)

            # restore A/M times
            os.utime(origin_pio_ini,
                     (getatime(back_pio_ini), getmtime(back_pio_ini)))
        except NotPlatformIOProjectError as e:
            raise pb.Error(str(e))

        cmd_args = ["platformio", "--force", command, "-d", project_dir]
        for env in options.get("environment", []):
            cmd_args.extend(["-e", env])
        for target in options.get("target", []):
            cmd_args.extend(["-t", target])
        for ignore in options.get("ignore", []):
            cmd_args.extend(["-i", ignore])
        if options.get("upload_port", False):
            cmd_args.extend(["--upload-port", options.get("upload_port")])
        if options.get("test_port", False):
            cmd_args.extend(["--test-port", options.get("test_port")])
        if options.get("disable_auto_clean", False):
            cmd_args.append("--disable-auto-clean")
        if options.get("without_building", False):
            cmd_args.append("--without-building")
        if options.get("without_uploading", False):
            cmd_args.append("--without-uploading")
        if options.get("silent", False):
            cmd_args.append("-s")
        if options.get("verbose", False):
            cmd_args.append("-v")

        paused_acs = []
        for ac in self._acs.values():
            if not isinstance(ac, SerialPortAsyncCmd):
                continue
            self.log.info("Pause active monitor at {port}",
                          port=ac.options["port"])
            ac.pause()
            paused_acs.append(ac)

        def _cb_on_end():
            if isfile(back_pio_ini):
                if isfile(origin_pio_ini):
                    os.remove(origin_pio_ini)
                os.rename(back_pio_ini, origin_pio_ini)
            for ac in paused_acs:
                ac.unpause()
                self.log.info("Unpause active monitor at {port}",
                              port=ac.options["port"])

        return self._defer_async_cmd(
            ProcessAsyncCmd(
                {
                    "executable": proc.where_is_program("platformio"),
                    "args": cmd_args
                },
                on_end_callback=_cb_on_end,
            ))
예제 #30
0
    for env in cfg.envs():
        platform = cfg.get("env:{}".format(env), "platform")
        if "espressif8266" in platform:
            yield {"chip": "esp8266", "env": env}
        elif "espressif32" in platform:
            yield {"chip": "esp32", "env": env}
        else:
            raise ValueError("Unknown `platform = {}` for `[env:{}]`".format(
                platform, env))


def filter_jobs(jobs, ignore=("spec_", )):
    for job in jobs:
        if job["env"].startswith(ignore):
            continue

        yield job


if __name__ == "__main__":
    jobs = list(filter_jobs(get_jobs(ProjectConfig.get_instance())))

    sort = []
    for job in jobs:
        if job["chip"] == "esp8266":
            sort.append(job["env"])
        sort.sort(key=str.casefold)

    serialized = json.dumps({"include": jobs})
    print("::set-output name=matrix::{}".format(serialized))