Esempio n. 1
0
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
Esempio n. 2
0
    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
Esempio n. 3
0
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
Esempio n. 4
0
    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
Esempio n. 5
0
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)
Esempio n. 6
0
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"],
        )
Esempio n. 7
0
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()]))
Esempio n. 8
0
 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)
Esempio n. 9
0
 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)
Esempio n. 10
0
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
Esempio n. 11
0
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
Esempio n. 12
0
        "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])
Esempio n. 13
0
    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),
        )
Esempio n. 14
0
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