def build_contrib_pysite_deps(target_dir): if os.path.isdir(target_dir): util.rmtree_(target_dir) os.makedirs(target_dir) with open(os.path.join(target_dir, "package.json"), "w") as fp: json.dump( dict( name="contrib-pysite", version="2.%d%d.0" % (sys.version_info.major, sys.version_info.minor), system=util.get_systype(), ), fp, ) pythonexe = get_pythonexe_path() for dep in get_contrib_pysite_deps(): subprocess.call([ pythonexe, "-m", "pip", "install", "--no-cache-dir", "--no-compile", "-t", target_dir, dep, ]) return True
def _run_scons(self, variables, targets, jobs): args = [ get_pythonexe_path(), join(get_core_package_dir("tool-scons"), "script", "scons"), "-Q", "--warn=no-no-parallel-support", "--jobs", str(jobs), "--sconstruct", join(fs.get_source_dir(), "builder", "main.py") ] # yapf: disable args.append("PIOVERBOSE=%d" % (1 if self.verbose else 0)) # pylint: disable=protected-access args.append("ISATTY=%d" % (1 if click._compat.isatty(sys.stdout) else 0)) args += targets # encode and append variables for key, value in variables.items(): args.append("%s=%s" % (key.upper(), self.encode_scons_arg(value))) def _write_and_flush(stream, data): try: stream.write(data) stream.flush() except IOError: pass copy_pythonpath_to_osenv() result = exec_command( args, stdout=BuildAsyncPipe( line_callback=self._on_stdout_line, data_callback=lambda data: _write_and_flush(sys.stdout, data)), stderr=BuildAsyncPipe( line_callback=self._on_stderr_line, data_callback=lambda data: _write_and_flush(sys.stderr, data))) return result
def cli(dev): if not dev and __version__ == get_latest_version(): return click.secho( "You're up-to-date!\nPlatformIO %s is currently the " "newest version available." % __version__, fg="green") click.secho("Please wait while upgrading PlatformIO ...", fg="yellow") # kill all PIO Home servers, they block `pioplus` binary shutdown_piohome_servers() to_develop = dev or not all(c.isdigit() for c in __version__ if c != ".") cmds = (["pip", "install", "--upgrade", get_pip_package(to_develop)], ["platformio", "--version"]) cmd = None r = {} try: for cmd in cmds: cmd = [get_pythonexe_path(), "-m"] + cmd r = exec_command(cmd) # try pip with disabled cache if r['returncode'] != 0 and cmd[2] == "pip": cmd.insert(3, "--no-cache-dir") r = exec_command(cmd) assert r['returncode'] == 0 assert "version" in r['out'] actual_version = r['out'].strip().split("version", 1)[1].strip() click.secho("PlatformIO has been successfully upgraded to %s" % actual_version, fg="green") click.echo("Release notes: ", nl=False) click.secho("https://docs.platformio.org/en/latest/history.html", fg="cyan") except Exception as e: # pylint: disable=broad-except if not r: raise exception.UpgradeError("\n".join([str(cmd), str(e)])) permission_errors = ("permission denied", "not permitted") if (any(m in r['err'].lower() for m in permission_errors) and not WINDOWS): click.secho(""" ----------------- Permission denied ----------------- You need the `sudo` permission to install Python packages. Try > sudo pip install -U platformio WARNING! Don't use `sudo` for the rest PlatformIO commands. """, fg="yellow", err=True) raise exception.ReturnErrorCode(1) raise exception.UpgradeError("\n".join([str(cmd), r['out'], r['err']])) return True
def configure_command(self, language, src_file): # pylint: disable=arguments-differ tool_path = os.path.join(get_core_package_dir("tool-cppcheck"), "cppcheck") cmd = [ tool_path, "--addon-python=%s" % proc.get_pythonexe_path(), "--error-exitcode=3", "--verbose" if self.options.get("verbose") else "--quiet", ] cmd.append( '--template="%s"' % self._field_delimiter.join( ["{0}={{{0}}}".format(f) for f in self.defect_fields] ) ) flags = self.get_flags("cppcheck") if not flags: # by default user can suppress reporting individual defects # directly in code // cppcheck-suppress warningID cmd.append("--inline-suppr") if not self.is_flag_set("--platform", flags): cmd.append("--platform=unspecified") if not self.is_flag_set("--enable", flags): enabled_checks = [ "warning", "style", "performance", "portability", "unusedFunction", ] cmd.append("--enable=%s" % ",".join(enabled_checks)) if not self.is_flag_set("--language", flags): cmd.append("--language=" + language) build_flags = self.cxx_flags if language == "c++" else self.cc_flags for flag in build_flags: if "-std" in flag: # Standards with GNU extensions are not allowed cmd.append("-" + flag.replace("gnu", "c")) cmd.extend( ["-D%s" % d for d in self.cpp_defines + self.toolchain_defines[language]] ) cmd.extend(flags) cmd.extend( "--include=" + inc for inc in self.get_forced_includes(build_flags, self.cpp_includes) ) cmd.append("--includes-file=%s" % self._generate_inc_file()) cmd.append('"%s"' % src_file) return cmd
class BaseProcess(protocol.ProcessProtocol, object): STDOUT_CHUNK_SIZE = 2048 COMMON_PATTERNS = { "PLATFORMIO_HOME_DIR": get_project_core_dir(), "PLATFORMIO_CORE_DIR": get_project_core_dir(), "PYTHONEXE": get_pythonexe_path(), } def apply_patterns(self, source, patterns=None): _patterns = self.COMMON_PATTERNS.copy() _patterns.update(patterns or {}) for key, value in _patterns.items(): if key.endswith(("_DIR", "_PATH")): _patterns[key] = fs.to_unix_path(value) def _replace(text): for key, value in _patterns.items(): pattern = "$%s" % key text = text.replace(pattern, value or "") return text if isinstance(source, string_types): source = _replace(source) elif isinstance(source, (list, dict)): items = enumerate(source) if isinstance(source, list) else source.items() for key, value in items: if isinstance(value, string_types): source[key] = _replace(value) elif isinstance(value, (list, dict)): source[key] = self.apply_patterns(value, patterns) return source def outReceived(self, data): if LOG_FILE: with open(LOG_FILE, "ab") as fp: fp.write(data) while data: chunk = data[:self.STDOUT_CHUNK_SIZE] click.echo(chunk, nl=False) data = data[self.STDOUT_CHUNK_SIZE:] @staticmethod def errReceived(data): if LOG_FILE: with open(LOG_FILE, "ab") as fp: fp.write(data) click.echo(data, nl=False, err=True) @staticmethod def processEnded(_): # Allow terminating via SIGINT/CTRL+C signal.signal(signal.SIGINT, signal.default_int_handler)
def completion(): # pylint: disable=import-error,import-outside-toplevel try: import click_completion # pylint: disable=unused-import,unused-variable except ImportError: click.echo("Installing dependent packages...") subprocess.check_call( [proc.get_pythonexe_path(), "-m", "pip", "install", "click-completion"], )
def system_info(json_output): project_config = ProjectConfig() data = {} data["core_version"] = {"title": "PlatformIO Core", "value": __version__} data["python_version"] = { "title": "Python", "value": "{0}.{1}.{2}-{3}.{4}".format(*list(sys.version_info)), } data["system"] = {"title": "System Type", "value": util.get_systype()} data["platform"] = { "title": "Platform", "value": platform.platform(terse=True) } data["filesystem_encoding"] = { "title": "File System Encoding", "value": compat.get_filesystem_encoding(), } data["locale_encoding"] = { "title": "Locale Encoding", "value": compat.get_locale_encoding(), } data["core_dir"] = { "title": "PlatformIO Core Directory", "value": project_config.get_optional_dir("core"), } data["platformio_exe"] = { "title": "PlatformIO Core Executable", "value": proc.where_is_program( "platformio.exe" if proc.WINDOWS else "platformio"), } data["python_exe"] = { "title": "Python Executable", "value": proc.get_pythonexe_path(), } data["global_lib_nums"] = { "title": "Global Libraries", "value": len(LibraryPackageManager().get_installed()), } data["dev_platform_nums"] = { "title": "Development Platforms", "value": len(PlatformPackageManager().get_installed()), } data["package_tool_nums"] = { "title": "Tools & Toolchains", "value": len( ToolPackageManager( project_config.get_optional_dir("packages")).get_installed()), } click.echo( json.dumps(data) if json_output else tabulate([( item["title"], item["value"]) for item in data.values()]))
def uninstall_python_packages(self): if not self.python_packages: return click.echo("Uninstalling Python packages") args = [proc.get_pythonexe_path(), "-m", "pip", "uninstall", "--yes"] args.extend(list(self.python_packages.keys())) try: subprocess.call(args) == 0 except Exception as e: # pylint: disable=broad-except click.secho("Could not install Python packages -> %s" % e, fg="red", err=True)
def install_python_packages(self): if not self.python_packages: return None click.echo( "Installing Python packages: %s" % ", ".join(list(self.python_packages.keys())), ) args = [proc.get_pythonexe_path(), "-m", "pip", "install", "--upgrade"] for name, requirements in self.python_packages.items(): if any(c in requirements for c in ("<", ">", "=")): args.append("%s%s" % (name, requirements)) else: args.append("%s==%s" % (name, requirements)) try: return subprocess.call(args) == 0 except Exception as e: # pylint: disable=broad-except click.secho("Could not install Python packages -> %s" % e, fg="red", err=True)
def build_contrib_pysite_deps(target_dir): if os.path.isdir(target_dir): fs.rmtree(target_dir) os.makedirs(target_dir) # build dependencies pythonexe = get_pythonexe_path() for dep in get_contrib_pysite_deps(): subprocess.check_call([ pythonexe, "-m", "pip", "install", # "--no-cache-dir", "--no-compile", "--no-binary", ":all:", "-t", target_dir, dep, ]) # build manifests with open(os.path.join(target_dir, "package.json"), "w") as fp: json.dump( dict( name="contrib-pysite", version="2.%d%d.%s" % ( sys.version_info.major, sys.version_info.minor, date.today().strftime("%y%m%d"), ), system=util.get_systype(), ), fp, ) pm = ToolPackageManager() pkg = PackageItem(target_dir) pkg.metadata = pm.build_metadata( target_dir, PackageSpec(owner="platformio", name="contrib-pysite")) pkg.dump_meta() return True
def pioplus_call(args, **kwargs): if WINDOWS and sys.version_info < (2, 7, 6): raise exception.PlatformioException( "PlatformIO Core Plus v%s does not run under Python version %s.\n" "Minimum supported version is 2.7.6, please upgrade Python.\n" "Python 3 is not yet supported.\n" % (__version__, sys.version)) pioplus_path = join(get_core_package_dir("tool-pioplus"), "pioplus") pythonexe_path = get_pythonexe_path() os.environ["PYTHONEXEPATH"] = pythonexe_path os.environ["PYTHONPYSITEDIR"] = get_core_package_dir("contrib-pysite") os.environ["PIOCOREPYSITEDIR"] = dirname(fs.get_source_dir() or "") if dirname(pythonexe_path) not in os.environ["PATH"].split(os.pathsep): os.environ["PATH"] = (os.pathsep).join( [dirname(pythonexe_path), os.environ["PATH"]]) copy_pythonpath_to_osenv() code = subprocess.call([pioplus_path] + args, **kwargs) # handle remote update request if code == 13: count_attr = "_update_count" try: count_value = getattr(pioplus_call, count_attr) except AttributeError: count_value = 0 setattr(pioplus_call, count_attr, 1) count_value += 1 setattr(pioplus_call, count_attr, count_value) if count_value < PIOPLUS_AUTO_UPDATES_MAX: update_core_packages() return pioplus_call(args, **kwargs) # handle reload request elif code == 14: return pioplus_call(args, **kwargs) if code != 0: raise exception.ReturnErrorCode(1) return True
"piomisc", "pioide", "piosize", ], toolpath=[join(fs.get_source_dir(), "builder", "tools")], variables=clivars, # Propagating External Environment ENV=environ, UNIX_TIME=int(time()), BUILD_DIR=join("$PROJECT_BUILD_DIR", "$PIOENV"), BUILD_SRC_DIR=join("$BUILD_DIR", "src"), BUILD_TEST_DIR=join("$BUILD_DIR", "test"), LIBPATH=["$BUILD_DIR"], PROGNAME="program", PROG_PATH=join("$BUILD_DIR", "$PROGNAME$PROGSUFFIX"), PYTHONEXE=get_pythonexe_path(), ) if not int(ARGUMENTS.get("PIOVERBOSE", 0)): DEFAULT_ENV_OPTIONS["ARCOMSTR"] = "Archiving $TARGET" DEFAULT_ENV_OPTIONS["LINKCOMSTR"] = "Linking $TARGET" DEFAULT_ENV_OPTIONS["RANLIBCOMSTR"] = "Indexing $TARGET" for k in ("ASCOMSTR", "ASPPCOMSTR", "CCCOMSTR", "CXXCOMSTR"): DEFAULT_ENV_OPTIONS[k] = "Compiling $TARGET" env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS) # Load variables from CLI env.Replace( **{ key: PlatformBase.decode_scons_arg(env[key])
def _run_scons(self, variables, targets, jobs): scons_dir = get_core_package_dir("tool-scons") script_path = (os.path.join(scons_dir, "script", "scons") if PY2 else os.path.join(scons_dir, "scons.py")) args = [ proc.get_pythonexe_path(), script_path, "-Q", "--warn=no-no-parallel-support", "--jobs", str(jobs), "--sconstruct", os.path.join(fs.get_source_dir(), "builder", "main.py"), ] args.append("PIOVERBOSE=%d" % (1 if self.verbose else 0)) # pylint: disable=protected-access args.append("ISATTY=%d" % (1 if click._compat.isatty(sys.stdout) else 0)) args += targets # encode and append variables for key, value in variables.items(): args.append("%s=%s" % (key.upper(), self.encode_scons_arg(value))) proc.copy_pythonpath_to_osenv() if targets and "menuconfig" in targets: return proc.exec_command(args, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin) if click._compat.isatty(sys.stdout): def _write_and_flush(stream, data): try: stream.write(data) stream.flush() except IOError: pass return proc.exec_command( args, stdout=proc.BuildAsyncPipe( line_callback=self._on_stdout_line, data_callback=lambda data: None if self.silent else _write_and_flush(sys.stdout, data), ), stderr=proc.BuildAsyncPipe( line_callback=self._on_stderr_line, data_callback=lambda data: _write_and_flush( sys.stderr, data), ), ) return proc.exec_command( args, stdout=proc.LineBufferedAsyncPipe( line_callback=self._on_stdout_line), stderr=proc.LineBufferedAsyncPipe( line_callback=self._on_stderr_line), )
def build_contrib_pysite_package(target_dir, with_metadata=True): systype = util.get_systype() if os.path.isdir(target_dir): fs.rmtree(target_dir) os.makedirs(target_dir) # build dependencies args = [ get_pythonexe_path(), "-m", "pip", "install", "--no-compile", "-t", target_dir, ] if "linux" in systype: args.extend(["--no-binary", ":all:"]) for dep in get_contrib_pysite_deps(): subprocess.check_call(args + [dep]) # build manifests with open(os.path.join(target_dir, "package.json"), "w") as fp: json.dump( dict( name="contrib-pysite", version="2.%d%d.%s" % ( sys.version_info.major, sys.version_info.minor, date.today().strftime("%y%m%d"), ), system=list( set([systype, "linux_armv6l", "linux_armv7l", "linux_armv8l"]) ) if systype.startswith("linux_arm") else systype, description="Extra Python package for PlatformIO Core", keywords=["platformio", "platformio-core"], homepage="https://docs.platformio.org/page/core/index.html", repository={ "type": "git", "url": "https://github.com/platformio/platformio-core", }, ), fp, ) # generate package metadata if with_metadata: pm = ToolPackageManager() pkg = PackageItem(target_dir) pkg.metadata = pm.build_metadata( target_dir, PackageSpec(owner="platformio", name="contrib-pysite") ) pkg.dump_meta() # remove unused files for root, dirs, files in os.walk(target_dir): for t in ("_test", "test", "tests"): if t in dirs: shutil.rmtree(os.path.join(root, t)) for name in files: if name.endswith((".chm", ".pyc")): os.remove(os.path.join(root, name)) return target_dir