2014-06-07 13:34:31 +03:00
|
|
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
|
|
|
# See LICENSE for details.
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
from imp import load_source
|
|
|
|
from os import listdir
|
2014-11-29 22:39:44 +02:00
|
|
|
from os.path import isdir, isfile, join
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-12-03 14:18:22 +02:00
|
|
|
from platformio import exception
|
2014-11-29 22:39:44 +02:00
|
|
|
from platformio.app import get_state_item, set_state_item
|
2014-06-07 13:34:31 +03:00
|
|
|
from platformio.pkgmanager import PackageManager
|
2014-11-29 22:39:44 +02:00
|
|
|
from platformio.util import exec_command, get_home_dir, get_source_dir
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
|
|
|
|
class PlatformFactory(object):
|
|
|
|
|
2014-11-24 21:36:44 +02:00
|
|
|
@staticmethod
|
|
|
|
def get_clsname(name):
|
|
|
|
return "%sPlatform" % name.title()
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
@staticmethod
|
2014-11-29 22:39:44 +02:00
|
|
|
def load_module(name, path):
|
|
|
|
module = None
|
|
|
|
try:
|
|
|
|
module = load_source(
|
|
|
|
"platformio.platforms.%s" % name, path)
|
|
|
|
except ImportError:
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.UnknownPlatform(name)
|
2014-11-29 22:39:44 +02:00
|
|
|
return module
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_platforms(cls, installed=False):
|
2014-11-22 23:55:17 +02:00
|
|
|
platforms = {}
|
2014-11-24 21:36:44 +02:00
|
|
|
for d in (get_home_dir(), get_source_dir()):
|
|
|
|
pdir = join(d, "platforms")
|
2014-11-29 22:39:44 +02:00
|
|
|
if not isdir(pdir):
|
|
|
|
continue
|
2014-11-24 21:36:44 +02:00
|
|
|
for p in listdir(pdir):
|
|
|
|
if p in ("__init__.py", "base.py") or not p.endswith(".py"):
|
|
|
|
continue
|
|
|
|
name = p[:-3]
|
|
|
|
path = join(pdir, p)
|
|
|
|
try:
|
|
|
|
isplatform = hasattr(
|
2014-11-29 22:39:44 +02:00
|
|
|
cls.load_module(name, path),
|
|
|
|
cls.get_clsname(name)
|
2014-11-24 21:36:44 +02:00
|
|
|
)
|
|
|
|
if isplatform:
|
|
|
|
platforms[name] = path
|
2014-12-03 14:18:22 +02:00
|
|
|
except exception.UnknownPlatform:
|
2014-11-24 21:36:44 +02:00
|
|
|
pass
|
2014-11-22 23:55:17 +02:00
|
|
|
|
|
|
|
if not installed:
|
|
|
|
return platforms
|
|
|
|
|
|
|
|
installed_platforms = {}
|
2014-11-29 22:39:44 +02:00
|
|
|
for name in get_state_item("installed_platforms", []):
|
|
|
|
if name in platforms:
|
|
|
|
installed_platforms[name] = platforms[name]
|
2014-11-22 23:55:17 +02:00
|
|
|
return installed_platforms
|
|
|
|
|
2014-11-29 22:39:44 +02:00
|
|
|
@classmethod
|
|
|
|
def newPlatform(cls, name):
|
|
|
|
platforms = cls.get_platforms()
|
2014-11-24 21:36:44 +02:00
|
|
|
if name not in platforms:
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.UnknownPlatform(name)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-24 21:36:44 +02:00
|
|
|
_instance = getattr(
|
2014-11-29 22:39:44 +02:00
|
|
|
cls.load_module(name, platforms[name]),
|
|
|
|
cls.get_clsname(name)
|
2014-11-24 21:36:44 +02:00
|
|
|
)()
|
|
|
|
assert isinstance(_instance, BasePlatform)
|
|
|
|
return _instance
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
|
|
|
|
class BasePlatform(object):
|
|
|
|
|
|
|
|
PACKAGES = {}
|
|
|
|
|
|
|
|
def get_name(self):
|
2014-11-24 21:36:44 +02:00
|
|
|
return self.__class__.__name__[:-8].lower()
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def get_build_script(self):
|
|
|
|
builtin = join(get_source_dir(), "builder", "scripts", "%s.py" %
|
|
|
|
self.get_name())
|
|
|
|
if isfile(builtin):
|
|
|
|
return builtin
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
2014-06-12 23:29:47 +03:00
|
|
|
def get_short_info(self):
|
|
|
|
if self.__doc__:
|
|
|
|
doclines = [l.strip() for l in self.__doc__.splitlines()]
|
|
|
|
return " ".join(doclines).strip()
|
|
|
|
else:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def get_packages(self):
|
|
|
|
return self.PACKAGES
|
|
|
|
|
2014-07-30 23:39:01 +03:00
|
|
|
def get_pkg_alias(self, pkgname):
|
|
|
|
return self.PACKAGES[pkgname].get("alias", None)
|
|
|
|
|
2014-07-30 23:08:36 +03:00
|
|
|
def pkg_aliases_to_names(self, aliases):
|
|
|
|
names = []
|
|
|
|
for alias in aliases:
|
|
|
|
name = alias
|
2014-11-22 23:55:17 +02:00
|
|
|
# lookup by package aliases
|
|
|
|
for _name, _opts in self.get_packages().items():
|
|
|
|
if _opts.get("alias", None) == alias:
|
|
|
|
name = _name
|
|
|
|
break
|
2014-07-30 23:08:36 +03:00
|
|
|
names.append(name)
|
|
|
|
return names
|
2014-07-30 22:40:11 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def get_installed_packages(self):
|
|
|
|
pm = PackageManager()
|
|
|
|
return [n for n in self.get_packages().keys() if pm.is_installed(n)]
|
|
|
|
|
2014-07-30 22:40:11 +03:00
|
|
|
def install(self, with_packages, without_packages, skip_default_packages):
|
2014-07-30 23:08:36 +03:00
|
|
|
with_packages = set(self.pkg_aliases_to_names(with_packages))
|
|
|
|
without_packages = set(self.pkg_aliases_to_names(without_packages))
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-07-30 22:40:11 +03:00
|
|
|
upkgs = with_packages | without_packages
|
2014-11-22 23:55:17 +02:00
|
|
|
ppkgs = set(self.get_packages().keys())
|
2014-07-30 23:08:36 +03:00
|
|
|
if not upkgs.issubset(ppkgs):
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.UnknownPackage(", ".join(upkgs - ppkgs))
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-07-30 22:40:11 +03:00
|
|
|
requirements = []
|
2014-11-22 23:55:17 +02:00
|
|
|
for name, opts in self.get_packages().items():
|
2014-06-07 13:34:31 +03:00
|
|
|
if name in without_packages:
|
|
|
|
continue
|
2014-07-30 22:40:11 +03:00
|
|
|
elif (name in with_packages or (not skip_default_packages and
|
|
|
|
opts['default'])):
|
2014-11-22 23:55:17 +02:00
|
|
|
requirements.append(name)
|
|
|
|
|
|
|
|
pm = PackageManager()
|
|
|
|
for name in requirements:
|
|
|
|
pm.install(name)
|
|
|
|
|
|
|
|
# register installed platform
|
2014-11-29 22:39:44 +02:00
|
|
|
data = get_state_item("installed_platforms", [])
|
|
|
|
if self.get_name() not in data:
|
|
|
|
data.append(self.get_name())
|
|
|
|
set_state_item("installed_platforms", data)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-07-30 22:40:11 +03:00
|
|
|
return len(requirements)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
|
|
|
def uninstall(self):
|
|
|
|
platform = self.get_name()
|
2014-11-22 23:55:17 +02:00
|
|
|
installed_platforms = PlatformFactory.get_platforms(
|
|
|
|
installed=True).keys()
|
|
|
|
|
|
|
|
if platform not in installed_platforms:
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.PlatformNotInstalledYet(platform)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
deppkgs = set()
|
|
|
|
for item in installed_platforms:
|
|
|
|
if item == platform:
|
|
|
|
continue
|
2014-12-03 20:16:50 +02:00
|
|
|
p = PlatformFactory.newPlatform(item)
|
2014-11-22 23:55:17 +02:00
|
|
|
deppkgs = deppkgs.union(set(p.get_packages().keys()))
|
|
|
|
|
|
|
|
pm = PackageManager()
|
|
|
|
for name in self.get_packages().keys():
|
2014-11-24 22:24:19 +02:00
|
|
|
if not pm.is_installed(name) or name in deppkgs:
|
2014-11-22 23:55:17 +02:00
|
|
|
continue
|
|
|
|
pm.uninstall(name)
|
|
|
|
|
|
|
|
# unregister installed platform
|
2014-11-29 22:39:44 +02:00
|
|
|
installed_platforms.remove(platform)
|
|
|
|
set_state_item("installed_platforms", installed_platforms)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
return True
|
|
|
|
|
2014-06-13 20:47:02 +03:00
|
|
|
def update(self):
|
2014-11-22 23:55:17 +02:00
|
|
|
pm = PackageManager()
|
|
|
|
for name in self.get_installed_packages():
|
|
|
|
pm.update(name)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-29 22:39:44 +02:00
|
|
|
def is_outdated(self):
|
|
|
|
pm = PackageManager()
|
|
|
|
obsolated = pm.get_outdated()
|
|
|
|
return not set(self.get_packages().keys()).isdisjoint(set(obsolated))
|
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
def run(self, variables, targets):
|
|
|
|
assert isinstance(variables, list)
|
|
|
|
assert isinstance(targets, list)
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
installed_platforms = PlatformFactory.get_platforms(
|
|
|
|
installed=True).keys()
|
|
|
|
installed_packages = PackageManager.get_installed()
|
|
|
|
|
|
|
|
if self.get_name() not in installed_platforms:
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.PlatformNotInstalledYet(self.get_name())
|
2014-11-22 23:55:17 +02:00
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
if "clean" in targets:
|
|
|
|
targets.remove("clean")
|
|
|
|
targets.append("-c")
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
if not any([v.startswith("BUILD_SCRIPT=") for v in variables]):
|
|
|
|
variables.append("BUILD_SCRIPT=%s" % self.get_build_script())
|
|
|
|
|
|
|
|
for v in variables:
|
|
|
|
if not v.startswith("BUILD_SCRIPT="):
|
|
|
|
continue
|
|
|
|
_, path = v.split("=", 2)
|
|
|
|
if not isfile(path):
|
2014-12-03 14:18:22 +02:00
|
|
|
raise exception.BuildScriptNotFound(path)
|
2014-11-22 23:55:17 +02:00
|
|
|
|
2014-12-03 14:18:22 +02:00
|
|
|
# append aliases of the installed packages
|
2014-11-22 23:55:17 +02:00
|
|
|
for name, options in self.get_packages().items():
|
2015-02-03 18:44:24 +02:00
|
|
|
if "alias" not in options or name not in installed_packages:
|
2014-11-22 23:55:17 +02:00
|
|
|
continue
|
|
|
|
variables.append(
|
|
|
|
"PIOPACKAGE_%s=%s" % (options['alias'].upper(), name))
|
|
|
|
|
2014-12-03 14:18:22 +02:00
|
|
|
try:
|
|
|
|
result = exec_command([
|
|
|
|
"scons",
|
|
|
|
"-Q",
|
|
|
|
"-f", join(get_source_dir(), "builder", "main.py")
|
|
|
|
] + variables + targets)
|
|
|
|
except OSError:
|
|
|
|
raise exception.SConsNotInstalled()
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
return self.after_run(result)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
|
|
|
def after_run(self, result): # pylint: disable=R0201
|
|
|
|
return result
|