mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-31 02:27:13 +02:00
Merge branch 'feature/library-manager' into develop
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
VERSION = (0, 7, "0-dev")
|
VERSION = (0, 7, "0.dev")
|
||||||
__version__ = ".".join([str(s) for s in VERSION])
|
__version__ = ".".join([str(s) for s in VERSION])
|
||||||
|
|
||||||
__title__ = "platformio"
|
__title__ = "platformio"
|
||||||
@ -14,4 +14,6 @@ __email__ = "me@ikravets.com"
|
|||||||
__license__ = "MIT License"
|
__license__ = "MIT License"
|
||||||
__copyright__ = "Copyright (C) 2014 Ivan Kravets"
|
__copyright__ = "Copyright (C) 2014 Ivan Kravets"
|
||||||
|
|
||||||
|
# __apiurl__ = "http://127.0.0.1:8080"
|
||||||
|
__apiurl__ = "http://api.platformio.ikravets.com"
|
||||||
__pkgmanifesturl__ = "http://platformio.ikravets.com/packages/manifest.json"
|
__pkgmanifesturl__ = "http://platformio.ikravets.com/packages/manifest.json"
|
||||||
|
@ -16,7 +16,8 @@ from os.path import isdir, join
|
|||||||
from SCons.Script import (DefaultEnvironment, Exit, SConscript,
|
from SCons.Script import (DefaultEnvironment, Exit, SConscript,
|
||||||
SConscriptChdir, Variables)
|
SConscriptChdir, Variables)
|
||||||
|
|
||||||
from platformio.util import get_pioenvs_dir, get_project_dir, get_source_dir
|
from platformio.util import (get_lib_dir, get_pioenvs_dir, get_project_dir,
|
||||||
|
get_source_dir)
|
||||||
|
|
||||||
# AllowSubstExceptions()
|
# AllowSubstExceptions()
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ DefaultEnvironment(
|
|||||||
BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"),
|
BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"),
|
||||||
LIBSOURCE_DIRS=[
|
LIBSOURCE_DIRS=[
|
||||||
join("$PROJECT_DIR", "lib"),
|
join("$PROJECT_DIR", "lib"),
|
||||||
|
get_lib_dir(),
|
||||||
join("$PLATFORMFW_DIR", "libraries"),
|
join("$PLATFORMFW_DIR", "libraries"),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -165,8 +165,9 @@ def ConvertInotoCpp(env):
|
|||||||
remove(f)
|
remove(f)
|
||||||
|
|
||||||
tmpcpp = []
|
tmpcpp = []
|
||||||
|
items = (env.Glob(join("$PROJECT_DIR", "src", "*.ino")) +
|
||||||
for item in env.Glob(join("$PROJECT_DIR", "src", "*.ino")):
|
env.Glob(join("$PROJECT_DIR", "src", "*.pde")))
|
||||||
|
for item in items:
|
||||||
cppfile = item.get_path()[:-3] + "cpp"
|
cppfile = item.get_path()[:-3] + "cpp"
|
||||||
if isfile(cppfile):
|
if isfile(cppfile):
|
||||||
continue
|
continue
|
||||||
|
124
platformio/commands/lib.py
Normal file
124
platformio/commands/lib.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
||||||
|
# See LICENSE for details.
|
||||||
|
|
||||||
|
from urllib import quote
|
||||||
|
|
||||||
|
from click import argument, echo, group, option, secho, style
|
||||||
|
|
||||||
|
from platformio.exception import LibAlreadyInstalledError
|
||||||
|
from platformio.libmanager import LibraryManager
|
||||||
|
from platformio.util import get_api_result, get_lib_dir
|
||||||
|
|
||||||
|
|
||||||
|
@group(short_help="Library Manager")
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("search", short_help="Search for library")
|
||||||
|
@argument("query")
|
||||||
|
def lib_search(query):
|
||||||
|
result = get_api_result("/lib/search", dict(query=quote(query)))
|
||||||
|
secho("Found %d libraries:" % result['total'],
|
||||||
|
fg="green" if result['total'] else "yellow")
|
||||||
|
for item in result['items']:
|
||||||
|
echo("{name:<30} {description}".format(
|
||||||
|
name=style(item['name'], fg="cyan"),
|
||||||
|
description=item['description']
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("install", short_help="Install library")
|
||||||
|
@argument("names", nargs=-1)
|
||||||
|
@option("-v", "--version")
|
||||||
|
def lib_install_cli(names, version):
|
||||||
|
lib_install(names, version)
|
||||||
|
|
||||||
|
|
||||||
|
def lib_install(names, version=None):
|
||||||
|
lm = LibraryManager(get_lib_dir())
|
||||||
|
for name in names:
|
||||||
|
echo("Installing %s library:" % style(name, fg="cyan"))
|
||||||
|
try:
|
||||||
|
if lm.install(name, version):
|
||||||
|
secho("The library '%s' has been successfully installed!" %
|
||||||
|
name, fg="green")
|
||||||
|
except LibAlreadyInstalledError:
|
||||||
|
secho("Already installed", fg="yellow")
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("uninstall", short_help="Uninstall libraries")
|
||||||
|
@argument("names", nargs=-1)
|
||||||
|
def lib_uninstall_cli(names):
|
||||||
|
lib_uninstall(names)
|
||||||
|
|
||||||
|
|
||||||
|
def lib_uninstall(names):
|
||||||
|
lm = LibraryManager(get_lib_dir())
|
||||||
|
for name in names:
|
||||||
|
if lm.uninstall(name):
|
||||||
|
secho("The library '%s' has been successfully "
|
||||||
|
"uninstalled!" % name, fg="green")
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("list", short_help="List installed libraries")
|
||||||
|
def lib_list():
|
||||||
|
lm = LibraryManager(get_lib_dir())
|
||||||
|
for name in lm.get_installed():
|
||||||
|
info = lm.get_info(name)
|
||||||
|
echo("{name:<30} {description}".format(
|
||||||
|
name=style(info['name'], fg="cyan"),
|
||||||
|
description=info['description']
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("show", short_help="Show details about installed libraries")
|
||||||
|
@argument("name")
|
||||||
|
def lib_show(name):
|
||||||
|
lm = LibraryManager(get_lib_dir())
|
||||||
|
info = lm.get_info(name)
|
||||||
|
secho(info['name'], fg="cyan")
|
||||||
|
echo("-" * len(info['name']))
|
||||||
|
|
||||||
|
if "author" in info:
|
||||||
|
_data = []
|
||||||
|
for k in ("name", "email"):
|
||||||
|
if k in info['author'] and info['author'][k] is not None:
|
||||||
|
_value = info['author'][k]
|
||||||
|
if k == "email":
|
||||||
|
_value = "<%s>" % _value
|
||||||
|
_data.append(_value)
|
||||||
|
echo("Author: %s" % " ".join(_data))
|
||||||
|
|
||||||
|
echo("Keywords: %s" % info['keywords'])
|
||||||
|
echo("Version: %s" % info['version'])
|
||||||
|
echo()
|
||||||
|
echo(info['description'])
|
||||||
|
echo()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("update", short_help="Update installed libraries")
|
||||||
|
def lib_update():
|
||||||
|
lm = LibraryManager(get_lib_dir())
|
||||||
|
lib_names = lm.get_installed()
|
||||||
|
versions = get_api_result("/lib/version/" + ",".join(lib_names))
|
||||||
|
|
||||||
|
for name in lib_names:
|
||||||
|
info = lm.get_info(name)
|
||||||
|
|
||||||
|
echo("Updating %s library:" % style(name, fg="yellow"))
|
||||||
|
|
||||||
|
current_version = info['version']
|
||||||
|
latest_version = versions[name]
|
||||||
|
|
||||||
|
echo("Versions: Current=%s, Latest=%s \t " % (
|
||||||
|
current_version, latest_version), nl=False)
|
||||||
|
|
||||||
|
if current_version == latest_version:
|
||||||
|
echo("[%s]" % (style("Up-to-date", fg="green")))
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
echo("[%s]" % (style("Out-of-date", fg="red")))
|
||||||
|
|
||||||
|
lib_uninstall([name])
|
||||||
|
lib_install([name])
|
@ -10,7 +10,7 @@ from platformio.pkgmanager import PackageManager
|
|||||||
from platformio.platforms.base import PlatformFactory
|
from platformio.platforms.base import PlatformFactory
|
||||||
|
|
||||||
|
|
||||||
@command("show", short_help="Show details about an installed platforms")
|
@command("show", short_help="Show details about installed platforms")
|
||||||
@argument("platform")
|
@argument("platform")
|
||||||
def cli(platform):
|
def cli(platform):
|
||||||
p = PlatformFactory().newPlatform(platform)
|
p = PlatformFactory().newPlatform(platform)
|
||||||
|
@ -105,3 +105,17 @@ class GetSerialPortsError(PlatformioException):
|
|||||||
class GetLatestVersionError(PlatformioException):
|
class GetLatestVersionError(PlatformioException):
|
||||||
|
|
||||||
MESSAGE = "Can't retrieve latest PlatformIO version"
|
MESSAGE = "Can't retrieve latest PlatformIO version"
|
||||||
|
|
||||||
|
|
||||||
|
class APIRequestError(PlatformioException):
|
||||||
|
|
||||||
|
MESSAGE = "[API] %s"
|
||||||
|
|
||||||
|
|
||||||
|
class LibAlreadyInstalledError(PlatformioException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LibNotInstalledError(PlatformioException):
|
||||||
|
|
||||||
|
MESSAGE = "Library '%s' has not been installed yet"
|
||||||
|
75
platformio/libmanager.py
Normal file
75
platformio/libmanager.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
||||||
|
# See LICENSE for details.
|
||||||
|
|
||||||
|
import json
|
||||||
|
from os import listdir, makedirs, remove
|
||||||
|
from os.path import isdir, isfile, join
|
||||||
|
from shutil import rmtree
|
||||||
|
from tempfile import gettempdir
|
||||||
|
|
||||||
|
from platformio.downloader import FileDownloader
|
||||||
|
from platformio.exception import LibAlreadyInstalledError, LibNotInstalledError
|
||||||
|
from platformio.unpacker import FileUnpacker
|
||||||
|
from platformio.util import get_api_result
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryManager(object):
|
||||||
|
|
||||||
|
CONFIG_NAME = "library.json"
|
||||||
|
|
||||||
|
def __init__(self, lib_dir):
|
||||||
|
self.lib_dir = lib_dir
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def download(url, dest_dir):
|
||||||
|
fd = FileDownloader(url, dest_dir)
|
||||||
|
fd.start()
|
||||||
|
return fd.get_filepath()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def unpack(pkgpath, dest_dir):
|
||||||
|
fu = FileUnpacker(pkgpath, dest_dir)
|
||||||
|
return fu.start()
|
||||||
|
|
||||||
|
def get_installed(self):
|
||||||
|
items = []
|
||||||
|
for item in listdir(self.lib_dir):
|
||||||
|
conf_path = join(self.lib_dir, item, self.CONFIG_NAME)
|
||||||
|
if isfile(conf_path):
|
||||||
|
items.append(item)
|
||||||
|
return items
|
||||||
|
|
||||||
|
def get_info(self, name):
|
||||||
|
conf_path = join(self.lib_dir, name, self.CONFIG_NAME)
|
||||||
|
if not isfile(conf_path):
|
||||||
|
raise LibNotInstalledError(name)
|
||||||
|
with open(conf_path, "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def is_installed(self, name):
|
||||||
|
return isfile(join(self.lib_dir, name, self.CONFIG_NAME))
|
||||||
|
|
||||||
|
def install(self, name, version=None):
|
||||||
|
if self.is_installed(name):
|
||||||
|
raise LibAlreadyInstalledError()
|
||||||
|
|
||||||
|
_lib_dir = join(self.lib_dir, name)
|
||||||
|
if not isdir(_lib_dir):
|
||||||
|
makedirs(_lib_dir)
|
||||||
|
|
||||||
|
dlinfo = get_api_result("/lib/download/" + name, dict(version=version)
|
||||||
|
if version else None)
|
||||||
|
try:
|
||||||
|
dlpath = self.download(dlinfo['url'], gettempdir())
|
||||||
|
self.unpack(dlpath, _lib_dir)
|
||||||
|
finally:
|
||||||
|
remove(dlpath)
|
||||||
|
|
||||||
|
return self.is_installed(name)
|
||||||
|
|
||||||
|
def uninstall(self, name):
|
||||||
|
if self.is_installed(name):
|
||||||
|
rmtree(join(self.lib_dir, name))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise LibNotInstalledError(name)
|
@ -8,9 +8,14 @@ from platform import system, uname
|
|||||||
from subprocess import PIPE, Popen
|
from subprocess import PIPE, Popen
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from requests import get
|
||||||
|
from requests.exceptions import ConnectionError, HTTPError
|
||||||
|
from requests.utils import default_user_agent
|
||||||
from serial import Serial
|
from serial import Serial
|
||||||
|
|
||||||
from platformio.exception import GetSerialPortsError, NotPlatformProject
|
from platformio import __apiurl__, __version__
|
||||||
|
from platformio.exception import (APIRequestError, GetSerialPortsError,
|
||||||
|
NotPlatformProject)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
@ -36,6 +41,17 @@ def get_home_dir():
|
|||||||
return expanduser("~/.platformio")
|
return expanduser("~/.platformio")
|
||||||
|
|
||||||
|
|
||||||
|
def get_lib_dir():
|
||||||
|
try:
|
||||||
|
config = get_project_config()
|
||||||
|
if (config.has_section("platformio") and
|
||||||
|
config.has_option("platformio", "lib_dir")):
|
||||||
|
return config.get("platformio", "lib_dir")
|
||||||
|
except NotPlatformProject:
|
||||||
|
pass
|
||||||
|
return join(get_home_dir(), "lib")
|
||||||
|
|
||||||
|
|
||||||
def get_source_dir():
|
def get_source_dir():
|
||||||
return dirname(realpath(__file__))
|
return dirname(realpath(__file__))
|
||||||
|
|
||||||
@ -96,3 +112,27 @@ def get_serialports():
|
|||||||
else:
|
else:
|
||||||
raise GetSerialPortsError(os_name)
|
raise GetSerialPortsError(os_name)
|
||||||
return[{"port": p, "description": d, "hwid": h} for p, d, h in comports()]
|
return[{"port": p, "description": d, "hwid": h} for p, d, h in comports()]
|
||||||
|
|
||||||
|
|
||||||
|
def get_api_result(path, params=None):
|
||||||
|
result = None
|
||||||
|
r = None
|
||||||
|
try:
|
||||||
|
headers = {"User-Agent": "PlatformIO/%s %s" % (
|
||||||
|
__version__, default_user_agent())}
|
||||||
|
r = get(__apiurl__ + path, params=params, headers=headers)
|
||||||
|
result = r.json()
|
||||||
|
r.raise_for_status()
|
||||||
|
except HTTPError as e:
|
||||||
|
if result and "errors" in result:
|
||||||
|
raise APIRequestError(result['errors'][0]['title'])
|
||||||
|
else:
|
||||||
|
raise APIRequestError(e)
|
||||||
|
except ConnectionError:
|
||||||
|
raise APIRequestError("Could not connect to PlatformIO API Service")
|
||||||
|
except ValueError:
|
||||||
|
raise APIRequestError("Invalid response: %s" % r.text)
|
||||||
|
finally:
|
||||||
|
if r:
|
||||||
|
r.close()
|
||||||
|
return result
|
||||||
|
Reference in New Issue
Block a user