Files
platformio-core/platformio/platforms/base.py

223 lines
7.0 KiB
Python
Raw Normal View History

# 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
from os.path import isfile, join
2014-11-22 23:55:17 +02:00
from platformio.exception import (BuildScriptNotFound, PlatformNotInstalledYet,
UnknownPackage, UnknownPlatform)
from platformio.pkgmanager import PackageManager
from platformio.util import (AppState, exec_command, get_home_dir,
get_source_dir)
class PlatformFactory(object):
@staticmethod
def get_clsname(name):
return "%sPlatform" % name.title()
2014-11-22 23:55:17 +02:00
@staticmethod
def get_platforms(installed=False):
platforms = {}
for d in (get_home_dir(), get_source_dir()):
pdir = join(d, "platforms")
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(
PlatformFactory.load_module(name, path),
PlatformFactory.get_clsname(name)
)
if isplatform:
platforms[name] = path
except UnknownPlatform:
pass
2014-11-22 23:55:17 +02:00
if not installed:
return platforms
installed_platforms = {}
with AppState() as state:
for name in state.get("installed_platforms", []):
if name in platforms:
installed_platforms[name] = platforms[name]
return installed_platforms
@staticmethod
def load_module(name, path):
module = None
try:
module = load_source(
"platformio.platforms.%s" % name, path)
except ImportError:
raise UnknownPlatform(name)
return module
@staticmethod
def newPlatform(name):
2014-11-22 23:55:17 +02:00
platforms = PlatformFactory.get_platforms()
if name not in platforms:
raise UnknownPlatform(name)
_instance = getattr(
PlatformFactory.load_module(name, platforms[name]),
PlatformFactory.get_clsname(name)
)()
assert isinstance(_instance, BasePlatform)
return _instance
class BasePlatform(object):
PACKAGES = {}
def get_name(self):
return self.__class__.__name__[:-8].lower()
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()
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
def get_pkg_alias(self, pkgname):
return self.PACKAGES[pkgname].get("alias", None)
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
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):
with_packages = set(self.pkg_aliases_to_names(with_packages))
without_packages = set(self.pkg_aliases_to_names(without_packages))
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())
if not upkgs.issubset(ppkgs):
raise UnknownPackage(", ".join(upkgs - ppkgs))
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():
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
with AppState() as state:
data = state.get("installed_platforms", [])
if self.get_name() not in data:
data.append(self.get_name())
state['installed_platforms'] = data
2014-07-30 22:40:11 +03:00
return len(requirements)
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:
raise PlatformNotInstalledYet(platform)
2014-11-22 23:55:17 +02:00
deppkgs = set()
for item in installed_platforms:
if item == platform:
continue
p = PlatformFactory().newPlatform(item)
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
with AppState() as state:
installed_platforms.remove(platform)
state['installed_platforms'] = installed_platforms
return True
def update(self):
2014-11-22 23:55:17 +02:00
pm = PackageManager()
for name in self.get_installed_packages():
pm.update(name)
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:
raise PlatformNotInstalledYet(self.get_name())
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):
raise BuildScriptNotFound(path)
# append aliases of installed packages
for name, options in self.get_packages().items():
if name not in installed_packages:
continue
variables.append(
"PIOPACKAGE_%s=%s" % (options['alias'].upper(), name))
result = exec_command([
"scons",
"-Q",
"-f", join(get_source_dir(), "builder", "main.py")
] + variables + targets)
return self.after_run(result)
def after_run(self, result): # pylint: disable=R0201
return result