From 983b629d2359eb3acf49ea8a386ad86ef89bb337 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 15 Feb 2015 23:53:15 +0200 Subject: [PATCH] Implement asynchronous output for build process --- HISTORY.rst | 3 +++ platformio/commands/run.py | 13 ++++++------- platformio/platforms/atmelavr.py | 10 +++++----- platformio/platforms/base.py | 33 +++++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 75bc13ca..29fd1083 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,6 +19,9 @@ Release History (`issue #42 `_) * Allowed to ignore some libs from *Library Dependency Finder* via `ignore_libs `_ option +* Improved `platformio run `__ + command: asynchronous output for build process, timing and detailed + information about environment configuration (`issue #74 `_) * Output compiled size and static memory usage with `platformio run `__ command (`issue #59 `_) * Updated `framework-arduino` AVR & SAM to 1.6 stable version diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 2e7bf242..0c0725ce 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -36,6 +36,7 @@ def cli(ctx, environment, target, upload_port): getmtime(_pioenvs_dir)): rmtree(_pioenvs_dir) + _first_processing = True for section in config.sections(): # skip main configuration section if section == "platformio": @@ -54,6 +55,10 @@ def cli(ctx, environment, target, upload_port): process_environment(ctx, envname, options, target, upload_port) + if not _first_processing: + click.echo() + _first_processing = False + def process_environment(ctx, name, options, targets, upload_port): terminal_width, _ = click.get_terminal_size() @@ -67,12 +72,7 @@ def process_environment(ctx, name, options, targets, upload_port): click.secho("-" * terminal_width, bold=True) result = _run_environment(ctx, name, options, targets, upload_port) - is_error = "Error" in result['err'] - - click.secho(result['out'], fg="green") - if result['err']: - click.secho(result['err'], err=True, - fg="red" if is_error else "yellow") + is_error = "error" in result['err'].lower() summary_text = " Took %.2f seconds " % (time() - start_time) half_line = "=" * ((terminal_width - len(summary_text) - 10) / 2) @@ -83,7 +83,6 @@ def process_environment(ctx, name, options, targets, upload_port): summary_text, half_line ), err=is_error) - click.echo() def _run_environment(ctx, name, options, targets, upload_port): diff --git a/platformio/platforms/atmelavr.py b/platformio/platforms/atmelavr.py index 1d0d891c..1ca85ded 100644 --- a/platformio/platforms/atmelavr.py +++ b/platformio/platforms/atmelavr.py @@ -27,9 +27,9 @@ class AtmelavrPlatform(BasePlatform): } } - def after_run(self, result): + def on_run_err(self, line): # pylint: disable=R0201 # fix STDERR "flash written" for avrdude - if "flash written" in result['err']: - result['out'] += "\n" + result['err'] - result['err'] = "" - return result + if "flash written" in line: + self.on_run_out(line) + else: + BasePlatform.on_run_err(self, line) diff --git a/platformio/platforms/base.py b/platformio/platforms/base.py index 98b547c0..ad950318 100644 --- a/platformio/platforms/base.py +++ b/platformio/platforms/base.py @@ -5,10 +5,11 @@ from imp import load_source from os import listdir from os.path import isdir, isfile, join -from platformio import exception +import click + +from platformio import exception, util from platformio.app import get_state_item, set_state_item from platformio.pkgmanager import PackageManager -from platformio.util import exec_command, get_home_dir, get_source_dir class PlatformFactory(object): @@ -30,7 +31,7 @@ class PlatformFactory(object): @classmethod def get_platforms(cls, installed=False): platforms = {} - for d in (get_home_dir(), get_source_dir()): + for d in (util.get_home_dir(), util.get_source_dir()): pdir = join(d, "platforms") if not isdir(pdir): continue @@ -80,7 +81,7 @@ class BasePlatform(object): return self.__class__.__name__[:-8].lower() def get_build_script(self): - builtin = join(get_source_dir(), "builder", "scripts", "%s.py" % + builtin = join(util.get_source_dir(), "builder", "scripts", "%s.py" % self.get_name()) if isfile(builtin): return builtin @@ -214,11 +215,15 @@ class BasePlatform(object): "PIOPACKAGE_%s=%s" % (options['alias'].upper(), name)) try: - result = exec_command([ - "scons", - "-Q", - "-f", join(get_source_dir(), "builder", "main.py") - ] + variables + targets) + result = util.exec_command( + [ + "scons", + "-Q", + "-f", join(util.get_source_dir(), "builder", "main.py") + ] + variables + targets, + stdout=util.AsyncPipe(self.on_run_out), + stderr=util.AsyncPipe(self.on_run_err) + ) except OSError: raise exception.SConsNotInstalled() @@ -226,3 +231,13 @@ class BasePlatform(object): def after_run(self, result): # pylint: disable=R0201 return result + + def on_run_out(self, line): # pylint: disable=R0201 + fg = None + if "is up to date" in line: + fg = "green" + click.secho(line, fg=fg) + + def on_run_err(self, line): # pylint: disable=R0201 + click.secho(line, err=True, + fg="red" if "error" in line.lower() else "yellow")