forked from platformio/platformio-core
Implement asynchronous command execution (AsyncPipe+subprocess)
This commit is contained in:
@ -2,11 +2,11 @@
|
|||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from os import name as os_name
|
import os
|
||||||
from os import getcwd, getenv, listdir, makedirs, utime
|
import subprocess
|
||||||
from os.path import abspath, dirname, expanduser, isdir, isfile, join, realpath
|
from os.path import abspath, dirname, expanduser, isdir, isfile, join, realpath
|
||||||
from platform import system, uname
|
from platform import system, uname
|
||||||
from subprocess import PIPE, Popen
|
from threading import Thread
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@ -18,6 +18,39 @@ except ImportError:
|
|||||||
from ConfigParser import ConfigParser
|
from ConfigParser import ConfigParser
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
def get_systype():
|
def get_systype():
|
||||||
data = uname()
|
data = uname()
|
||||||
return ("%s_%s" % (data[0], data[4])).lower()
|
return ("%s_%s" % (data[0], data[4])).lower()
|
||||||
@ -38,7 +71,7 @@ def get_home_dir():
|
|||||||
home_dir = join(expanduser("~"), ".platformio")
|
home_dir = join(expanduser("~"), ".platformio")
|
||||||
|
|
||||||
if not isdir(home_dir):
|
if not isdir(home_dir):
|
||||||
makedirs(home_dir)
|
os.makedirs(home_dir)
|
||||||
|
|
||||||
assert isdir(home_dir)
|
assert isdir(home_dir)
|
||||||
return home_dir
|
return home_dir
|
||||||
@ -63,11 +96,11 @@ def get_source_dir():
|
|||||||
|
|
||||||
|
|
||||||
def get_project_dir():
|
def get_project_dir():
|
||||||
return getcwd()
|
return os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
def get_pioenvs_dir():
|
def get_pioenvs_dir():
|
||||||
return getenv("PIOENVS_DIR", join(get_project_dir(), ".pioenvs"))
|
return os.getenv("PIOENVS_DIR", join(get_project_dir(), ".pioenvs"))
|
||||||
|
|
||||||
|
|
||||||
def get_project_config():
|
def get_project_config():
|
||||||
@ -80,26 +113,48 @@ def get_project_config():
|
|||||||
|
|
||||||
|
|
||||||
def change_filemtime(path, time):
|
def change_filemtime(path, time):
|
||||||
utime(path, (time, time))
|
os.utime(path, (time, time))
|
||||||
|
|
||||||
|
|
||||||
def exec_command(*args, **kwargs):
|
def exec_command(*args, **kwargs):
|
||||||
kwargs['stdout'] = PIPE
|
result = {"out": None, "err": None}
|
||||||
kwargs['stderr'] = PIPE
|
default = dict(
|
||||||
kwargs['shell'] = system() == "Windows"
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
shell=system() == "Windows"
|
||||||
|
)
|
||||||
|
default.update(kwargs)
|
||||||
|
kwargs = default
|
||||||
|
|
||||||
p = Popen(*args, **kwargs)
|
p = subprocess.Popen(*args, **kwargs)
|
||||||
out, err = p.communicate()
|
try:
|
||||||
return dict(out=out.strip(), err=err.strip())
|
result['out'], result['err'] = p.communicate()
|
||||||
|
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():
|
||||||
|
if not v:
|
||||||
|
continue
|
||||||
|
result[k].strip()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_serialports():
|
def get_serialports():
|
||||||
if os_name == "nt":
|
if os.name == "nt":
|
||||||
from serial.tools.list_ports_windows import comports
|
from serial.tools.list_ports_windows import comports
|
||||||
elif os_name == "posix":
|
elif os.name == "posix":
|
||||||
from serial.tools.list_ports_posix import comports
|
from serial.tools.list_ports_posix import comports
|
||||||
else:
|
else:
|
||||||
raise exception.GetSerialPortsError(os_name)
|
raise exception.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()]
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +205,7 @@ def get_boards(type_=None):
|
|||||||
bdirs.append(join(get_home_dir(), "boards"))
|
bdirs.append(join(get_home_dir(), "boards"))
|
||||||
|
|
||||||
for bdir in bdirs:
|
for bdir in bdirs:
|
||||||
for json_file in listdir(bdir):
|
for json_file in os.listdir(bdir):
|
||||||
if not json_file.endswith(".json"):
|
if not json_file.endswith(".json"):
|
||||||
continue
|
continue
|
||||||
with open(join(bdir, json_file)) as f:
|
with open(join(bdir, json_file)) as f:
|
||||||
|
Reference in New Issue
Block a user