From 28d9f25f9abd000a1be45bb61c98c11b27a2a61e Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 12 Jun 2020 23:47:12 +0300 Subject: [PATCH] Added a new "-e, --environment" option to "platformio project init" command --- HISTORY.rst | 1 + docs | 2 +- examples | 2 +- platformio/commands/project.py | 28 ++++++++++++- platformio/ide/projectgenerator.py | 64 +++++++++++------------------- tests/commands/test_init.py | 37 +++++++++++++---- 6 files changed, 83 insertions(+), 51 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 0add5842..b725d474 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -17,6 +17,7 @@ PlatformIO Core 4 * Added support for `custom targets `__ (user cases: command shortcuts, pre/post processing based on dependencies, custom command launcher with options, etc.) * Added support for "globstar/`**`" (recursive) pattern for the different commands and configuration options (`platformio ci `__, `src_filter `__, `check_patterns `__, `library.json > srcFilter `__). Python 3.5+ is required. +* Added a new ``-e, --environment`` option to `platformio project init `__ command that helps to update a PlatformIO project using existing environment * Fixed an issue with PIO Unit Testing when running multiple environments (`issue #3523 `_) 4.3.4 (2020-05-23) diff --git a/docs b/docs index ec54ae99..2178afaf 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit ec54ae991784ce854dfe939bcaf4c2545abcf55e +Subproject commit 2178afaf333874a1f6d3dff4b45d0613517049b5 diff --git a/examples b/examples index c442de34..bcdcf466 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit c442de34a57b54451170dbe39f3411a06a05b3f2 +Subproject commit bcdcf46691c1fe79e8cb2cc74e1a156f6bac5e90 diff --git a/platformio/commands/project.py b/platformio/commands/project.py index 3d73f4ff..c83b44a7 100644 --- a/platformio/commands/project.py +++ b/platformio/commands/project.py @@ -93,6 +93,7 @@ def validate_boards(ctx, param, value): # pylint: disable=W0613 ) @click.option("-b", "--board", multiple=True, metavar="ID", callback=validate_boards) @click.option("--ide", type=click.Choice(ProjectGenerator.get_supported_ides())) +@click.option("-e", "--environment", help="Update using existing environment") @click.option("-O", "--project-option", multiple=True) @click.option("--env-prefix", default="") @click.option("-s", "--silent", is_flag=True) @@ -102,6 +103,7 @@ def project_init( project_dir, board, ide, + environment, project_option, env_prefix, silent, @@ -139,7 +141,11 @@ def project_init( ) if ide: - pg = ProjectGenerator(project_dir, ide, board) + 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: @@ -444,3 +450,23 @@ def _install_dependent_platforms(ctx, platforms): ctx.invoke( cli_platform_install, platforms=list(set(platforms) - set(installed_platforms)) ) + + +def get_best_envname(config, board_ids=None): + envname = None + default_envs = config.default_envs() + if default_envs: + envname = default_envs[0] + if not board_ids: + return envname + + for env in config.envs(): + if not board_ids: + return env + if not envname: + envname = env + items = config.items(env=env, as_dict=True) + if "board" in items and items.get("board") in board_ids: + return env + + return envname diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index 8bf735b0..30eaa97d 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -15,47 +15,31 @@ import codecs import os import sys -from os.path import basename, isdir, isfile, join, realpath, relpath import bottle from platformio import fs, util from platformio.proc import where_is_program -from platformio.project.config import ProjectConfig from platformio.project.helpers import load_project_ide_data class ProjectGenerator(object): - def __init__(self, project_dir, ide, boards): - self.config = ProjectConfig.get_instance(join(project_dir, "platformio.ini")) - self.config.validate() - self.project_dir = project_dir + def __init__(self, config, env_name, ide): + self.config = config + self.project_dir = os.path.dirname(config.path) + self.env_name = str(env_name) self.ide = str(ide) - self.env_name = str(self.get_best_envname(boards)) @staticmethod def get_supported_ides(): - tpls_dir = join(fs.get_source_dir(), "ide", "tpls") - return sorted([d for d in os.listdir(tpls_dir) if isdir(join(tpls_dir, d))]) - - def get_best_envname(self, boards=None): - envname = None - default_envs = self.config.default_envs() - if default_envs: - envname = default_envs[0] - if not boards: - return envname - - for env in self.config.envs(): - if not boards: - return env - if not envname: - envname = env - items = self.config.items(env=env, as_dict=True) - if "board" in items and items.get("board") in boards: - return env - - return envname + tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls") + return sorted( + [ + d + for d in os.listdir(tpls_dir) + if os.path.isdir(os.path.join(tpls_dir, d)) + ] + ) @staticmethod def filter_includes(includes_map, ignore_scopes=None, to_unix_path=True): @@ -75,12 +59,12 @@ class ProjectGenerator(object): tpl_vars = { "config": self.config, "systype": util.get_systype(), - "project_name": basename(self.project_dir), + "project_name": os.path.basename(self.project_dir), "project_dir": self.project_dir, "env_name": self.env_name, - "user_home_dir": realpath(fs.expanduser("~")), + "user_home_dir": os.path.realpath(fs.expanduser("~")), "platformio_path": sys.argv[0] - if isfile(sys.argv[0]) + if os.path.isfile(sys.argv[0]) else where_is_program("platformio"), "env_path": os.getenv("PATH"), "env_pathsep": os.pathsep, @@ -97,7 +81,7 @@ class ProjectGenerator(object): "src_files": self.get_src_files(), "project_src_dir": self.config.get_optional_dir("src"), "project_lib_dir": self.config.get_optional_dir("lib"), - "project_libdeps_dir": join( + "project_libdeps_dir": os.path.join( self.config.get_optional_dir("libdeps"), self.env_name ), } @@ -120,12 +104,12 @@ class ProjectGenerator(object): with fs.cd(self.project_dir): for root, _, files in os.walk(self.config.get_optional_dir("src")): for f in files: - result.append(relpath(join(root, f))) + result.append(os.path.relpath(os.path.join(root, f))) return result def get_tpls(self): tpls = [] - tpls_dir = join(fs.get_source_dir(), "ide", "tpls", self.ide) + tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls", self.ide) for root, _, files in os.walk(tpls_dir): for f in files: if not f.endswith(".tpl"): @@ -133,7 +117,7 @@ class ProjectGenerator(object): _relpath = root.replace(tpls_dir, "") if _relpath.startswith(os.sep): _relpath = _relpath[1:] - tpls.append((_relpath, join(root, f))) + tpls.append((_relpath, os.path.join(root, f))) return tpls def generate(self): @@ -141,12 +125,12 @@ class ProjectGenerator(object): for tpl_relpath, tpl_path in self.get_tpls(): dst_dir = self.project_dir if tpl_relpath: - dst_dir = join(self.project_dir, tpl_relpath) - if not isdir(dst_dir): + dst_dir = os.path.join(self.project_dir, tpl_relpath) + if not os.path.isdir(dst_dir): os.makedirs(dst_dir) - file_name = basename(tpl_path)[:-4] + file_name = os.path.basename(tpl_path)[:-4] contents = self._render_tpl(tpl_path, tpl_vars) - self._merge_contents(join(dst_dir, file_name), contents) + self._merge_contents(os.path.join(dst_dir, file_name), contents) @staticmethod def _render_tpl(tpl_path, tpl_vars): @@ -155,7 +139,7 @@ class ProjectGenerator(object): @staticmethod def _merge_contents(dst_path, contents): - if basename(dst_path) == ".gitignore" and isfile(dst_path): + if os.path.basename(dst_path) == ".gitignore" and os.path.isfile(dst_path): return with codecs.open(dst_path, "w", encoding="utf8") as fp: fp.write(contents) diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index b874ead7..09bd8cf9 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -62,29 +62,50 @@ def test_init_ide_without_board(clirunner, tmpdir): assert isinstance(result.exception, ProjectEnvsNotAvailableError) -def test_init_ide_atom(clirunner, validate_cliresult, tmpdir): +def test_init_ide_vscode(clirunner, validate_cliresult, tmpdir): with tmpdir.as_cwd(): result = clirunner.invoke( - cmd_init, ["--ide", "atom", "-b", "uno", "-b", "teensy31"] + cmd_init, ["--ide", "vscode", "-b", "uno", "-b", "teensy31"] ) validate_cliresult(result) validate_pioproject(str(tmpdir)) assert all( - [tmpdir.join(f).check() for f in (".clang_complete", ".gcc-flags.json")] + [ + tmpdir.join(".vscode").join(f).check() + for f in ("c_cpp_properties.json", "launch.json") + ] + ) + assert ( + "framework-arduino-avr" + in tmpdir.join(".vscode").join("c_cpp_properties.json").read() ) - assert "framework-arduino" in tmpdir.join(".clang_complete").read() # switch to NodeMCU - result = clirunner.invoke(cmd_init, ["--ide", "atom", "-b", "nodemcuv2"]) + result = clirunner.invoke(cmd_init, ["--ide", "vscode", "-b", "nodemcuv2"]) validate_cliresult(result) validate_pioproject(str(tmpdir)) - assert "arduinoespressif" in tmpdir.join(".clang_complete").read() + assert ( + "framework-arduinoespressif8266" + in tmpdir.join(".vscode").join("c_cpp_properties.json").read() + ) + + # switch to teensy31 via env name + result = clirunner.invoke(cmd_init, ["--ide", "vscode", "-e", "teensy31"]) + validate_cliresult(result) + validate_pioproject(str(tmpdir)) + assert ( + "framework-arduinoteensy" + in tmpdir.join(".vscode").join("c_cpp_properties.json").read() + ) # switch to the first board - result = clirunner.invoke(cmd_init, ["--ide", "atom"]) + result = clirunner.invoke(cmd_init, ["--ide", "vscode"]) validate_cliresult(result) validate_pioproject(str(tmpdir)) - assert "framework-arduino" in tmpdir.join(".clang_complete").read() + assert ( + "framework-arduino-avr" + in tmpdir.join(".vscode").join("c_cpp_properties.json").read() + ) def test_init_ide_eclipse(clirunner, validate_cliresult):