From 3b092f28c3a1347a4f719fc89db86a01917aee2c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 24 Jan 2020 19:47:47 +0200 Subject: [PATCH] Added support for "pythonPackages" in `platform.json` --- HISTORY.rst | 1 + docs | 2 +- platformio/managers/platform.py | 50 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 6fd1c6a4..3b290650 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,6 +19,7 @@ PlatformIO Core 4.0 - Added support for `PVS-Studio `__ static code analyzer * Control debug flags and optimization level with a new `debug_build_flags `__ option +* Added support for "pythonPackages" in `platform.json `__ manifest (PlatformIO Package Manager will install dependent Python packages from PyPi registry automatically when dev-platform is installed) * Handle project configuration (monitor, test, and upload options) for PIO Remote commands (`issue #2591 `_) * Updated SCons tool to 3.1.2 * Made package ManifestSchema compatible with marshmallow >= 3 (`issue #3296 `_) diff --git a/docs b/docs index a430de33..cfc5eed0 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a430de3311d1a033d2a5a6d6ac1c2b9597c6ffa3 +Subproject commit cfc5eed060900a8b5510c23e269b773019e3882f diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 5d61829e..983cab50 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -17,6 +17,7 @@ import base64 import os import re +import subprocess import sys from os.path import basename, dirname, isdir, isfile, join @@ -86,6 +87,8 @@ class PlatformManager(BasePkgManager): # don't cleanup packages or install them after update # we check packages for updates in def update() if after_update: + p.install_python_packages() + p.on_installed() return True p.install_packages( @@ -95,6 +98,8 @@ class PlatformManager(BasePkgManager): silent=silent, force=force, ) + p.install_python_packages() + p.on_installed() return self.cleanup_packages(list(p.packages)) def uninstall(self, package, requirements=None, after_update=False): @@ -109,6 +114,8 @@ class PlatformManager(BasePkgManager): p = PlatformFactory.newPlatform(pkg_dir) BasePkgManager.uninstall(self, pkg_dir, requirements) + p.uninstall_python_packages() + p.on_uninstalled() # don't cleanup packages or install them after update # we check packages for updates in def update() @@ -594,6 +601,10 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): packages[name].update({"version": version.strip(), "optional": False}) return packages + @property + def python_packages(self): + return self._manifest.get("pythonPackages") + def get_dir(self): return dirname(self.manifest_path) @@ -699,6 +710,45 @@ class PlatformBase(PlatformPackagesMixin, PlatformRunMixin): return [dict(name=name, path=path) for path, name in storages.items()] + def on_installed(self): + pass + + def on_uninstalled(self): + pass + + 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 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 + ) + class PlatformBoardConfig(object): def __init__(self, manifest_path):