forked from platformio/platformio-core
Support "force_ansi" option for core.exec and allow to raise exception on cmd error
This commit is contained in:
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools
|
import functools
|
||||||
|
import os
|
||||||
|
|
||||||
from platformio import __main__, __version__, app, proc, util
|
from platformio import __main__, __version__, app, proc, util
|
||||||
from platformio.compat import (
|
from platformio.compat import (
|
||||||
@ -21,10 +22,16 @@ from platformio.compat import (
|
|||||||
aio_create_task,
|
aio_create_task,
|
||||||
aio_get_running_loop,
|
aio_get_running_loop,
|
||||||
get_locale_encoding,
|
get_locale_encoding,
|
||||||
|
shlex_join,
|
||||||
)
|
)
|
||||||
|
from platformio.exception import UserSideException
|
||||||
from platformio.home.rpc.handlers.base import BaseRPCHandler
|
from platformio.home.rpc.handlers.base import BaseRPCHandler
|
||||||
|
|
||||||
|
|
||||||
|
class PIOCoreCallError(UserSideException):
|
||||||
|
MESSAGE = 'An error occured while executing PIO Core command: "{0}"\n\n{1}'
|
||||||
|
|
||||||
|
|
||||||
class PIOCoreProtocol(asyncio.SubprocessProtocol):
|
class PIOCoreProtocol(asyncio.SubprocessProtocol):
|
||||||
def __init__(self, exit_future, on_data_callback=None):
|
def __init__(self, exit_future, on_data_callback=None):
|
||||||
self.exit_future = exit_future
|
self.exit_future = exit_future
|
||||||
@ -66,27 +73,41 @@ class CoreRPC(BaseRPCHandler):
|
|||||||
def version():
|
def version():
|
||||||
return __version__
|
return __version__
|
||||||
|
|
||||||
async def exec(self, args, options=None):
|
async def exec(self, args, options=None, raise_exception=False):
|
||||||
|
options = options or {}
|
||||||
loop = aio_get_running_loop()
|
loop = aio_get_running_loop()
|
||||||
exit_future = loop.create_future()
|
exit_future = loop.create_future()
|
||||||
data_callback = functools.partial(
|
data_callback = functools.partial(
|
||||||
self._on_exec_data_received, exec_options=options
|
self._on_exec_data_received, exec_options=options
|
||||||
)
|
)
|
||||||
|
|
||||||
if args[0] != "--caller" and app.get_session_var("caller_id"):
|
if args[0] != "--caller" and app.get_session_var("caller_id"):
|
||||||
args = ["--caller", app.get_session_var("caller_id")] + args
|
args = ["--caller", app.get_session_var("caller_id")] + args
|
||||||
|
kwargs = options.get("spawn", {})
|
||||||
|
|
||||||
|
if "forceANSI" in options:
|
||||||
|
environ = kwargs.get("env", os.environ.copy())
|
||||||
|
environ["PLATFORMIO_FORCE_ANSI"] = "true"
|
||||||
|
kwargs["env"] = environ
|
||||||
|
|
||||||
transport, protocol = await loop.subprocess_exec(
|
transport, protocol = await loop.subprocess_exec(
|
||||||
lambda: PIOCoreProtocol(exit_future, data_callback),
|
lambda: PIOCoreProtocol(exit_future, data_callback),
|
||||||
get_core_fullpath(),
|
get_core_fullpath(),
|
||||||
*args,
|
*args,
|
||||||
stdin=None,
|
stdin=None,
|
||||||
**options.get("spawn", {}),
|
**kwargs,
|
||||||
)
|
)
|
||||||
await exit_future
|
await exit_future
|
||||||
transport.close()
|
transport.close()
|
||||||
|
return_code = transport.get_returncode()
|
||||||
|
if return_code != 0 and raise_exception:
|
||||||
|
raise PIOCoreCallError(
|
||||||
|
shlex_join(["pio"] + args), f"{protocol.stdout}\n{protocol.stderr}"
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"stdout": protocol.stdout,
|
"stdout": protocol.stdout,
|
||||||
"stderr": protocol.stderr,
|
"stderr": protocol.stderr,
|
||||||
"returncode": transport.get_returncode(),
|
"returncode": return_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _on_exec_data_received(self, exec_options, pipe, data):
|
def _on_exec_data_received(self, exec_options, pipe, data):
|
||||||
|
@ -48,19 +48,15 @@ class ProjectRPC(BaseRPCHandler):
|
|||||||
if not os.path.isdir(project_dir):
|
if not os.path.isdir(project_dir):
|
||||||
os.makedirs(project_dir)
|
os.makedirs(project_dir)
|
||||||
|
|
||||||
envclone = os.environ.copy()
|
args = ["project", "init", "-d", project_dir]
|
||||||
envclone["PLATFORMIO_FORCE_ANSI"] = "true"
|
|
||||||
options = options or {}
|
|
||||||
options["spawn"] = {"env": envclone, "cwd": project_dir}
|
|
||||||
|
|
||||||
args = ["project", "init"]
|
|
||||||
ide = app.get_session_var("caller_id")
|
ide = app.get_session_var("caller_id")
|
||||||
if ide in ProjectGenerator.get_supported_ides():
|
if ide in ProjectGenerator.get_supported_ides():
|
||||||
args.extend(["--ide", ide])
|
args.extend(["--ide", ide])
|
||||||
|
|
||||||
|
exec_options = options.get("exec", {})
|
||||||
if configuration.get("example"):
|
if configuration.get("example"):
|
||||||
await self.factory.notify_clients(
|
await self.factory.notify_clients(
|
||||||
method=options.get("stdoutNotificationMethod"),
|
method=exec_options.get("stdoutNotificationMethod"),
|
||||||
params=["Copying example files...\n"],
|
params=["Copying example files...\n"],
|
||||||
actor="frontend",
|
actor="frontend",
|
||||||
)
|
)
|
||||||
@ -68,7 +64,9 @@ class ProjectRPC(BaseRPCHandler):
|
|||||||
else:
|
else:
|
||||||
args.extend(self._pre_init_empty(configuration))
|
args.extend(self._pre_init_empty(configuration))
|
||||||
|
|
||||||
return await self.factory.manager.dispatcher["core.exec"](args, options=options)
|
return await self.factory.manager.dispatcher["core.exec"](
|
||||||
|
args, options=exec_options
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _pre_init_empty(configuration):
|
def _pre_init_empty(configuration):
|
||||||
@ -115,9 +113,9 @@ class ProjectRPC(BaseRPCHandler):
|
|||||||
def configuration(project_dir, env):
|
def configuration(project_dir, env):
|
||||||
assert is_platformio_project(project_dir)
|
assert is_platformio_project(project_dir)
|
||||||
with fs.cd(project_dir):
|
with fs.cd(project_dir):
|
||||||
config = ProjectConfig(os.path.join(project_dir, "platformio.ini"))
|
|
||||||
platform = PlatformFactory.from_env(env, autoinstall=True)
|
platform = PlatformFactory.from_env(env, autoinstall=True)
|
||||||
platform_pkg = PlatformPackageManager().get_package(platform.get_dir())
|
platform_pkg = PlatformPackageManager().get_package(platform.get_dir())
|
||||||
|
config = ProjectConfig.get_instance()
|
||||||
board_id = config.get(f"env:{env}", "board", None)
|
board_id = config.get(f"env:{env}", "board", None)
|
||||||
|
|
||||||
# frameworks
|
# frameworks
|
||||||
|
Reference in New Issue
Block a user