2014-05-18 23:38:59 +03:00
|
|
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
|
|
|
# See LICENSE for details.
|
|
|
|
|
2014-12-27 23:59:20 +02:00
|
|
|
import json
|
2015-02-15 23:48:04 +02:00
|
|
|
import os
|
|
|
|
import subprocess
|
2015-01-24 16:04:53 +01:00
|
|
|
from os.path import abspath, dirname, expanduser, isdir, isfile, join, realpath
|
2014-07-31 16:20:31 +03:00
|
|
|
from platform import system, uname
|
2015-02-15 23:48:04 +02:00
|
|
|
from threading import Thread
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
import requests
|
2014-05-18 23:38:59 +03:00
|
|
|
|
2015-02-13 23:01:01 +02:00
|
|
|
from platformio import __apiurl__, __version__, exception
|
2014-07-27 22:35:40 +03:00
|
|
|
|
2014-05-18 23:38:59 +03:00
|
|
|
try:
|
|
|
|
from configparser import ConfigParser
|
|
|
|
except ImportError:
|
2014-06-07 13:34:31 +03:00
|
|
|
from ConfigParser import ConfigParser
|
2014-05-18 23:38:59 +03:00
|
|
|
|
|
|
|
|
2015-02-15 23:48:04 +02:00
|
|
|
class AsyncPipe(Thread):
|
|
|
|
|
|
|
|
def __init__(self, outcallback=None):
|
|
|
|
Thread.__init__(self)
|
|
|
|
self.outcallback = outcallback
|
|
|
|
|
|
|
|
self._fd_read, self._fd_write = os.pipe()
|
|
|
|
self._pipe_reader = os.fdopen(self._fd_read)
|
|
|
|
self._buffer = []
|
|
|
|
|
|
|
|
self.start()
|
|
|
|
|
|
|
|
def get_buffer(self):
|
|
|
|
return self._buffer
|
|
|
|
|
|
|
|
def fileno(self):
|
|
|
|
return self._fd_write
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
for line in iter(self._pipe_reader.readline, ""):
|
|
|
|
line = line.strip()
|
|
|
|
self._buffer.append(line)
|
|
|
|
if self.outcallback:
|
|
|
|
self.outcallback(line)
|
|
|
|
else:
|
|
|
|
print line
|
|
|
|
self._pipe_reader.close()
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
os.close(self._fd_write)
|
|
|
|
self.join()
|
|
|
|
|
|
|
|
|
2014-07-31 16:20:31 +03:00
|
|
|
def get_systype():
|
|
|
|
data = uname()
|
|
|
|
return ("%s_%s" % (data[0], data[4])).lower()
|
2014-06-12 23:29:47 +03:00
|
|
|
|
|
|
|
|
2014-05-18 23:38:59 +03:00
|
|
|
def get_home_dir():
|
2014-11-22 23:55:17 +02:00
|
|
|
home_dir = None
|
|
|
|
|
2014-08-22 17:57:28 +03:00
|
|
|
try:
|
|
|
|
config = get_project_config()
|
|
|
|
if (config.has_section("platformio") and
|
|
|
|
config.has_option("platformio", "home_dir")):
|
2014-11-22 23:55:17 +02:00
|
|
|
home_dir = config.get("platformio", "home_dir")
|
2015-02-13 23:01:01 +02:00
|
|
|
except exception.NotPlatformProject:
|
2014-08-22 17:57:28 +03:00
|
|
|
pass
|
2014-11-22 23:55:17 +02:00
|
|
|
|
|
|
|
if not home_dir:
|
2015-01-29 18:50:12 +02:00
|
|
|
home_dir = join(expanduser("~"), ".platformio")
|
2014-11-22 23:55:17 +02:00
|
|
|
|
|
|
|
if not isdir(home_dir):
|
2015-02-15 23:48:04 +02:00
|
|
|
os.makedirs(home_dir)
|
2014-11-22 23:55:17 +02:00
|
|
|
|
|
|
|
assert isdir(home_dir)
|
|
|
|
return home_dir
|
2014-05-18 23:38:59 +03:00
|
|
|
|
|
|
|
|
2014-09-04 18:58:12 +03:00
|
|
|
def get_lib_dir():
|
|
|
|
try:
|
|
|
|
config = get_project_config()
|
|
|
|
if (config.has_section("platformio") and
|
|
|
|
config.has_option("platformio", "lib_dir")):
|
2015-01-24 16:14:44 +01:00
|
|
|
lib_dir = config.get("platformio", "lib_dir")
|
2014-10-04 23:30:51 +03:00
|
|
|
if lib_dir.startswith("~"):
|
2015-01-24 16:14:44 +01:00
|
|
|
lib_dir = expanduser(lib_dir)
|
|
|
|
return abspath(lib_dir)
|
2015-02-13 23:01:01 +02:00
|
|
|
except exception.NotPlatformProject:
|
2014-09-04 18:58:12 +03:00
|
|
|
pass
|
|
|
|
return join(get_home_dir(), "lib")
|
|
|
|
|
|
|
|
|
2014-05-18 23:38:59 +03:00
|
|
|
def get_source_dir():
|
|
|
|
return dirname(realpath(__file__))
|
|
|
|
|
|
|
|
|
|
|
|
def get_project_dir():
|
2015-02-15 23:48:04 +02:00
|
|
|
return os.getcwd()
|
2014-05-18 23:38:59 +03:00
|
|
|
|
|
|
|
|
2014-07-27 22:35:40 +03:00
|
|
|
def get_pioenvs_dir():
|
2015-02-15 23:48:04 +02:00
|
|
|
return os.getenv("PIOENVS_DIR", join(get_project_dir(), ".pioenvs"))
|
2014-07-27 22:35:40 +03:00
|
|
|
|
|
|
|
|
2014-05-18 23:38:59 +03:00
|
|
|
def get_project_config():
|
|
|
|
path = join(get_project_dir(), "platformio.ini")
|
|
|
|
if not isfile(path):
|
2015-02-13 23:01:01 +02:00
|
|
|
raise exception.NotPlatformProject(get_project_dir())
|
2014-06-07 13:34:31 +03:00
|
|
|
cp = ConfigParser()
|
|
|
|
cp.read(path)
|
|
|
|
return cp
|
|
|
|
|
2014-05-18 23:38:59 +03:00
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
def change_filemtime(path, time):
|
2015-02-15 23:48:04 +02:00
|
|
|
os.utime(path, (time, time))
|
2014-06-03 21:27:36 +03:00
|
|
|
|
|
|
|
|
2015-01-29 18:54:28 +02:00
|
|
|
def exec_command(*args, **kwargs):
|
2015-02-19 22:02:50 +02:00
|
|
|
result = {
|
|
|
|
"out": None,
|
|
|
|
"err": None,
|
|
|
|
"returncode": None
|
|
|
|
}
|
|
|
|
|
2015-02-15 23:48:04 +02:00
|
|
|
default = dict(
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
shell=system() == "Windows"
|
|
|
|
)
|
|
|
|
default.update(kwargs)
|
|
|
|
kwargs = default
|
|
|
|
|
|
|
|
p = subprocess.Popen(*args, **kwargs)
|
|
|
|
try:
|
|
|
|
result['out'], result['err'] = p.communicate()
|
2015-02-19 22:02:50 +02:00
|
|
|
result['returncode'] = p.returncode
|
2015-02-15 23:48:04 +02:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
for s in ("stdout", "stderr"):
|
|
|
|
if isinstance(kwargs[s], AsyncPipe):
|
|
|
|
kwargs[s].close()
|
|
|
|
raise exception.AbortedByUser()
|
|
|
|
|
|
|
|
for s in ("stdout", "stderr"):
|
|
|
|
if isinstance(kwargs[s], AsyncPipe):
|
|
|
|
kwargs[s].close()
|
|
|
|
result[s[3:]] = "\n".join(kwargs[s].get_buffer())
|
|
|
|
|
|
|
|
for k, v in result.iteritems():
|
2015-02-19 22:02:50 +02:00
|
|
|
if v and isinstance(v, basestring):
|
|
|
|
result[k].strip()
|
2015-01-29 18:54:28 +02:00
|
|
|
|
2015-02-15 23:48:04 +02:00
|
|
|
return result
|
2014-07-27 22:29:32 +03:00
|
|
|
|
|
|
|
|
|
|
|
def get_serialports():
|
2015-02-15 23:48:04 +02:00
|
|
|
if os.name == "nt":
|
2014-07-27 22:29:32 +03:00
|
|
|
from serial.tools.list_ports_windows import comports
|
2015-02-15 23:48:04 +02:00
|
|
|
elif os.name == "posix":
|
2014-07-27 22:29:32 +03:00
|
|
|
from serial.tools.list_ports_posix import comports
|
|
|
|
else:
|
2015-02-15 23:48:04 +02:00
|
|
|
raise exception.GetSerialPortsError(os.name)
|
2014-07-27 22:29:32 +03:00
|
|
|
return[{"port": p, "description": d, "hwid": h} for p, d, h in comports()]
|
2014-09-04 18:58:12 +03:00
|
|
|
|
|
|
|
|
2014-09-08 22:02:57 +03:00
|
|
|
def get_api_result(path, params=None, data=None):
|
2014-09-04 18:58:12 +03:00
|
|
|
result = None
|
|
|
|
r = None
|
2014-12-01 22:45:53 +02:00
|
|
|
|
2014-09-04 18:58:12 +03:00
|
|
|
try:
|
2014-12-24 21:36:11 +02:00
|
|
|
requests.packages.urllib3.disable_warnings()
|
2014-09-04 18:58:12 +03:00
|
|
|
headers = {"User-Agent": "PlatformIO/%s %s" % (
|
2014-11-22 23:55:17 +02:00
|
|
|
__version__, requests.utils.default_user_agent())}
|
2014-12-01 22:45:53 +02:00
|
|
|
# if packages - redirect to SF
|
|
|
|
if path == "/packages":
|
|
|
|
r = requests.get(
|
2014-12-24 22:12:42 +02:00
|
|
|
"http://sourceforge.net/projects/platformio-storage/files/"
|
2014-12-01 23:21:21 +02:00
|
|
|
"packages/manifest.json", params=params, headers=headers)
|
2014-12-01 22:45:53 +02:00
|
|
|
elif data:
|
2014-11-22 23:55:17 +02:00
|
|
|
r = requests.post(__apiurl__ + path, params=params, data=data,
|
|
|
|
headers=headers)
|
2014-09-08 22:02:57 +03:00
|
|
|
else:
|
2014-11-22 23:55:17 +02:00
|
|
|
r = requests.get(__apiurl__ + path, params=params, headers=headers)
|
2014-09-04 18:58:12 +03:00
|
|
|
result = r.json()
|
|
|
|
r.raise_for_status()
|
2014-11-22 23:55:17 +02:00
|
|
|
except requests.exceptions.HTTPError as e:
|
2014-09-04 18:58:12 +03:00
|
|
|
if result and "errors" in result:
|
2015-02-13 23:01:01 +02:00
|
|
|
raise exception.APIRequestError(result['errors'][0]['title'])
|
2014-09-04 18:58:12 +03:00
|
|
|
else:
|
2015-02-13 23:01:01 +02:00
|
|
|
raise exception.APIRequestError(e)
|
2014-11-22 23:55:17 +02:00
|
|
|
except requests.exceptions.ConnectionError:
|
2015-02-13 23:01:01 +02:00
|
|
|
raise exception.APIRequestError(
|
2014-10-19 00:14:11 +03:00
|
|
|
"Could not connect to PlatformIO Registry Service")
|
2014-09-04 18:58:12 +03:00
|
|
|
except ValueError:
|
2015-02-13 23:01:01 +02:00
|
|
|
raise exception.APIRequestError(
|
|
|
|
"Invalid response: %s" % r.text.encode("utf-8"))
|
2014-09-04 18:58:12 +03:00
|
|
|
finally:
|
|
|
|
if r:
|
|
|
|
r.close()
|
|
|
|
return result
|
2014-12-27 23:59:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
def get_boards(type_=None):
|
|
|
|
boards = {}
|
2015-02-13 23:01:01 +02:00
|
|
|
try:
|
|
|
|
boards = get_boards._cache # pylint: disable=W0212
|
|
|
|
except AttributeError:
|
|
|
|
bdirs = [join(get_source_dir(), "boards")]
|
|
|
|
if isdir(join(get_home_dir(), "boards")):
|
|
|
|
bdirs.append(join(get_home_dir(), "boards"))
|
|
|
|
|
|
|
|
for bdir in bdirs:
|
2015-02-15 23:48:04 +02:00
|
|
|
for json_file in os.listdir(bdir):
|
2015-02-13 23:01:01 +02:00
|
|
|
if not json_file.endswith(".json"):
|
|
|
|
continue
|
|
|
|
with open(join(bdir, json_file)) as f:
|
|
|
|
boards.update(json.load(f))
|
|
|
|
get_boards._cache = boards # pylint: disable=W0212
|
|
|
|
|
|
|
|
if type_ is None:
|
|
|
|
return boards
|
|
|
|
else:
|
|
|
|
if type_ not in boards:
|
|
|
|
raise exception.UnknownBoard(type_)
|
|
|
|
return boards[type_]
|