Improve printing of tabulated results

This commit is contained in:
Ivan Kravets
2019-08-17 20:55:16 +03:00
parent 9023358d9e
commit 0677bcecb9
16 changed files with 275 additions and 260 deletions

View File

@ -1,3 +1,3 @@
[settings] [settings]
line_length=79 line_length=79
known_third_party=bottle,click,pytest,requests,SCons,semantic_version,serial,twisted,autobahn,jsonrpc known_third_party=bottle,click,pytest,requests,SCons,semantic_version,serial,twisted,autobahn,jsonrpc,tabulate

View File

@ -79,10 +79,8 @@ DEFAULT_SETTINGS = {
}, },
"enable_telemetry": { "enable_telemetry": {
"description": "description":
("Telemetry service <https://docs.platformio.org/page/" ("Telemetry service <http://bit.ly/pio-telemetry> (Yes/No)"),
"userguide/cmd_settings.html?#enable-telemetry> (Yes/No)"), "value": True
"value":
True
}, },
"force_verbose": { "force_verbose": {
"description": "Force verbose output when processing environments", "description": "Force verbose output when processing environments",

View File

@ -15,6 +15,7 @@
import json import json
import click import click
from tabulate import tabulate
from platformio import fs from platformio import fs
from platformio.compat import dump_json_to_unicode from platformio.compat import dump_json_to_unicode
@ -42,32 +43,18 @@ def cli(query, installed, json_output): # pylint: disable=R0912
click.echo("") click.echo("")
click.echo("Platform: ", nl=False) click.echo("Platform: ", nl=False)
click.secho(platform, bold=True) click.secho(platform, bold=True)
click.echo("-" * terminal_width) click.echo("=" * terminal_width)
print_boards(boards) print_boards(boards)
return True return True
def print_boards(boards): def print_boards(boards):
terminal_width, _ = click.get_terminal_size()
BOARDLIST_TPL = ("{type:<30} {mcu:<14} {frequency:<8} "
" {flash:<7} {ram:<6} {name}")
click.echo( click.echo(
BOARDLIST_TPL.format(type=click.style("ID", fg="cyan"), tabulate([(click.style(b['id'], fg="cyan"), b['mcu'], "%dMHz" %
mcu="MCU", (b['fcpu'] / 1000000), fs.format_filesize(
frequency="Frequency", b['rom']), fs.format_filesize(b['ram']), b['name'])
flash="Flash", for b in boards],
ram="RAM", headers=["ID", "MCU", "Frequency", "Flash", "RAM", "Name"]))
name="Name"))
click.echo("-" * terminal_width)
for board in boards:
click.echo(
BOARDLIST_TPL.format(type=click.style(board['id'], fg="cyan"),
mcu=board['mcu'],
frequency="%dMHz" % (board['fcpu'] / 1000000),
flash=fs.format_filesize(board['rom']),
ram=fs.format_filesize(board['ram']),
name=board['name']))
def _get_boards(installed=False): def _get_boards(installed=False):

View File

@ -19,6 +19,7 @@ from os.path import isdir, join
import click import click
import semantic_version import semantic_version
from tabulate import tabulate
from platformio import exception, fs, util from platformio import exception, fs, util
from platformio.commands import PlatformioCLI from platformio.commands import PlatformioCLI
@ -486,66 +487,48 @@ def lib_stats(json_output):
if json_output: if json_output:
return click.echo(dump_json_to_unicode(result)) return click.echo(dump_json_to_unicode(result))
printitem_tpl = "{name:<33} {url}"
printitemdate_tpl = "{name:<33} {date:23} {url}"
def _print_title(title):
click.secho(title.upper(), bold=True)
click.echo("*" * len(title))
def _print_header(with_date=False):
click.echo((printitemdate_tpl if with_date else printitem_tpl).format(
name=click.style("Name", fg="cyan"),
date="Date",
url=click.style("Url", fg="blue")))
terminal_width, _ = click.get_terminal_size()
click.echo("-" * terminal_width)
def _print_lib_item(item):
date = str(
time.strftime("%c", util.parse_date(item['date'])) if "date" in
item else "")
url = click.style("https://platformio.org/lib/show/%s/%s" %
(item['id'], quote(item['name'])),
fg="blue")
click.echo(
(printitemdate_tpl if "date" in item else printitem_tpl).format(
name=click.style(item['name'], fg="cyan"), date=date, url=url))
def _print_tag_item(name):
click.echo(
printitem_tpl.format(
name=click.style(name, fg="cyan"),
url=click.style("https://platformio.org/lib/search?query=" +
quote("keyword:%s" % name),
fg="blue")))
for key in ("updated", "added"): for key in ("updated", "added"):
_print_title("Recently " + key) tabular_data = [(click.style(item['name'], fg="cyan"),
_print_header(with_date=True) time.strftime("%c", util.parse_date(item['date'])),
for item in result.get(key, []): "https://platformio.org/lib/show/%s/%s" %
_print_lib_item(item) (item['id'], quote(item['name'])))
for item in result.get(key, [])]
table = tabulate(tabular_data,
headers=[
click.style("RECENTLY " + key.upper(), bold=True),
"Date", "URL"
])
click.echo(table)
click.echo() click.echo()
_print_title("Recent keywords") for key in ("lastkeywords", "topkeywords"):
_print_header(with_date=False) tabular_data = [(click.style(name, fg="cyan"),
for item in result.get("lastkeywords"): "https://platformio.org/lib/search?query=" +
_print_tag_item(item) quote("keyword:%s" % name))
click.echo() for name in result.get(key, [])]
table = tabulate(
_print_title("Popular keywords") tabular_data,
_print_header(with_date=False) headers=[
for item in result.get("topkeywords"): click.style(
_print_tag_item(item) ("RECENT" if key == "lastkeywords" else "POPULAR") +
click.echo() " KEYWORDS",
bold=True), "URL"
])
click.echo(table)
click.echo()
for key, title in (("dlday", "Today"), ("dlweek", "Week"), ("dlmonth", for key, title in (("dlday", "Today"), ("dlweek", "Week"), ("dlmonth",
"Month")): "Month")):
_print_title("Featured: " + title) tabular_data = [(click.style(item['name'], fg="cyan"),
_print_header(with_date=False) "https://platformio.org/lib/show/%s/%s" %
for item in result.get(key, []): (item['id'], quote(item['name'])))
_print_lib_item(item) for item in result.get(key, [])]
table = tabulate(tabular_data,
headers=[
click.style("FEATURED: " + title.upper(),
bold=True), "URL"
])
click.echo(table)
click.echo() click.echo()
return True return True

View File

@ -13,4 +13,3 @@
# limitations under the License. # limitations under the License.
from platformio.commands.run.command import cli from platformio.commands.run.command import cli
from platformio.commands.run.helpers import print_header

View File

@ -18,13 +18,14 @@ from os.path import isfile, join
from time import time from time import time
import click import click
from tabulate import tabulate
from platformio import exception, fs from platformio import exception, fs, util
from platformio.commands.device import device_monitor as cmd_device_monitor from platformio.commands.device import device_monitor as cmd_device_monitor
from platformio.commands.run.helpers import (clean_build_dir, from platformio.commands.run.helpers import (clean_build_dir,
handle_legacy_libdeps, handle_legacy_libdeps)
print_summary)
from platformio.commands.run.processor import EnvironmentProcessor from platformio.commands.run.processor import EnvironmentProcessor
from platformio.commands.test.processor import CTX_META_TEST_IS_RUNNING
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
from platformio.project.helpers import (find_project_dir_above, from platformio.project.helpers import (find_project_dir_above,
get_project_build_dir) get_project_build_dir)
@ -73,6 +74,8 @@ def cli(ctx, environment, target, upload_port, project_dir, project_conf, jobs,
if isfile(project_dir): if isfile(project_dir):
project_dir = find_project_dir_above(project_dir) project_dir = find_project_dir_above(project_dir)
is_test_running = CTX_META_TEST_IS_RUNNING in ctx.meta
with fs.cd(project_dir): with fs.cd(project_dir):
config = ProjectConfig.get_instance( config = ProjectConfig.get_instance(
project_conf or join(project_dir, "platformio.ini")) project_conf or join(project_dir, "platformio.ini"))
@ -91,38 +94,112 @@ def cli(ctx, environment, target, upload_port, project_dir, project_conf, jobs,
handle_legacy_libdeps(project_dir, config) handle_legacy_libdeps(project_dir, config)
results = []
start_time = time()
default_envs = config.default_envs() default_envs = config.default_envs()
for envname in config.envs(): results = []
for env in config.envs():
skipenv = any([ skipenv = any([
environment and envname not in environment, not environment environment and env not in environment, not environment
and default_envs and envname not in default_envs and default_envs and env not in default_envs
]) ])
if skipenv: if skipenv:
results.append((envname, None)) results.append({"env": env})
continue continue
if not silent and any(status is not None # print empty line between multi environment project
for (_, status) in results): if not silent and any(
r.get("succeeded") is not None for r in results):
click.echo() click.echo()
ep = EnvironmentProcessor(ctx, envname, config, target, results.append(
upload_port, silent, verbose, jobs) process_env(ctx, env, config, environment, target, upload_port,
result = (envname, ep.process()) silent, verbose, jobs, is_test_running))
results.append(result)
if result[1] and "monitor" in ep.get_build_targets() and \ command_failed = any(r.get("succeeded") is False for r in results)
"nobuild" not in ep.get_build_targets():
ctx.invoke(cmd_device_monitor,
environment=environment[0] if environment else None)
found_error = any(status is False for (_, status) in results) if (not is_test_running and (command_failed or not silent)
and len(results) > 1):
print_processing_summary(results)
if (found_error or not silent) and len(results) > 1: if command_failed:
click.echo()
print_summary(results, start_time)
if found_error:
raise exception.ReturnErrorCode(1) raise exception.ReturnErrorCode(1)
return True return True
def process_env(ctx, name, config, environments, targets, upload_port, silent,
verbose, jobs, is_test_running):
if not is_test_running and not silent:
print_processing_header(name, config, verbose)
ep = EnvironmentProcessor(ctx, name, config, targets, upload_port, silent,
verbose, jobs)
result = {"env": name, "elapsed": time(), "succeeded": ep.process()}
result['elapsed'] = time() - result['elapsed']
# print footer on error or when is not unit testing
if not is_test_running and (not silent or not result['succeeded']):
print_processing_footer(result)
if (result['succeeded'] and "monitor" in ep.get_build_targets()
and "nobuild" not in ep.get_build_targets()):
ctx.invoke(cmd_device_monitor,
environment=environments[0] if environments else None)
return result
def print_processing_header(env, config, verbose=False):
env_dump = []
for k, v in config.items(env=env):
if verbose or k in ("platform", "framework", "board"):
env_dump.append("%s: %s" %
(k, ", ".join(v) if isinstance(v, list) else v))
click.echo("Processing %s (%s)" %
(click.style(env, fg="cyan", bold=True), "; ".join(env_dump)))
terminal_width, _ = click.get_terminal_size()
click.secho("-" * terminal_width, bold=True)
def print_processing_footer(result):
is_failed = not result.get("succeeded")
util.print_labeled_bar(
"[%s] Took %.2f seconds" %
((click.style("FAILED", fg="red", bold=True) if is_failed else
click.style("SUCCESS", fg="green", bold=True)), result['elapsed']),
is_error=is_failed)
def print_processing_summary(results):
tabular_data = []
succeeded_nums = 0
failed_nums = 0
elapsed = 0
for result in results:
elapsed += result.get("elapsed", 0)
if result.get("succeeded") is False:
failed_nums += 1
status_str = click.style("FAILED", fg="red")
elif result.get("succeeded") is None:
status_str = "IGNORED"
else:
succeeded_nums += 1
status_str = click.style("SUCCESS", fg="green")
tabular_data.append(
(click.style(result['env'], fg="cyan"), status_str,
util.humanize_elapsed_time(result.get("elapsed"))))
click.echo()
click.echo(tabulate(tabular_data,
headers=[
click.style(s, bold=True)
for s in ("Environment", "Status", "Time")
]),
err=failed_nums)
util.print_labeled_bar(
"%s%d succeeded in %s" %
("%d failed, " % failed_nums if failed_nums else "", succeeded_nums,
util.humanize_elapsed_time(elapsed)),
is_error=failed_nums,
fg="red" if failed_nums else "green")

View File

@ -14,7 +14,6 @@
from os import makedirs from os import makedirs
from os.path import isdir, isfile, join from os.path import isdir, isfile, join
from time import time
import click import click
@ -63,41 +62,3 @@ def clean_build_dir(build_dir, config):
makedirs(build_dir) makedirs(build_dir)
with open(checksum_file, "w") as f: with open(checksum_file, "w") as f:
f.write(checksum) f.write(checksum)
def print_header(label, is_error=False, fg=None):
terminal_width, _ = click.get_terminal_size()
width = len(click.unstyle(label))
half_line = "=" * int((terminal_width - width - 2) / 2)
click.secho("%s %s %s" % (half_line, label, half_line),
fg=fg,
err=is_error)
def print_summary(results, start_time):
print_header("[%s]" % click.style("SUMMARY"))
succeeded_nums = 0
failed_nums = 0
envname_max_len = max(
[len(click.style(envname, fg="cyan")) for (envname, _) in results])
for (envname, status) in results:
if status is False:
failed_nums += 1
status_str = click.style("FAILED", fg="red")
elif status is None:
status_str = click.style("IGNORED", fg="yellow")
else:
succeeded_nums += 1
status_str = click.style("SUCCESS", fg="green")
format_str = "Environment {0:<%d}\t[{1}]" % envname_max_len
click.echo(format_str.format(click.style(envname, fg="cyan"),
status_str),
err=status is False)
print_header("%s%d succeeded in %.2f seconds" %
("%d failed, " % failed_nums if failed_nums else "",
succeeded_nums, time() - start_time),
is_error=failed_nums,
fg="red" if failed_nums else "green")

View File

@ -12,16 +12,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from time import time
import click
from platformio import exception, telemetry from platformio import exception, telemetry
from platformio.commands.platform import \ from platformio.commands.platform import \
platform_install as cmd_platform_install platform_install as cmd_platform_install
from platformio.commands.run.helpers import print_header from platformio.commands.test.processor import CTX_META_TEST_RUNNING_NAME
from platformio.commands.test.processor import (CTX_META_TEST_IS_RUNNING,
CTX_META_TEST_RUNNING_NAME)
from platformio.managers.platform import PlatformFactory from platformio.managers.platform import PlatformFactory
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
@ -29,8 +23,6 @@ from platformio.managers.platform import PlatformFactory
class EnvironmentProcessor(object): class EnvironmentProcessor(object):
DEFAULT_PRINT_OPTIONS = ("platform", "framework", "board")
def __init__( # pylint: disable=too-many-arguments def __init__( # pylint: disable=too-many-arguments
self, cmd_ctx, name, config, targets, upload_port, silent, verbose, self, cmd_ctx, name, config, targets, upload_port, silent, verbose,
jobs): jobs):
@ -44,37 +36,6 @@ class EnvironmentProcessor(object):
self.jobs = jobs self.jobs = jobs
self.options = config.items(env=name, as_dict=True) self.options = config.items(env=name, as_dict=True)
def process(self):
terminal_width, _ = click.get_terminal_size()
start_time = time()
env_dump = []
for k, v in self.options.items():
if self.verbose or k in self.DEFAULT_PRINT_OPTIONS:
env_dump.append(
"%s: %s" % (k, ", ".join(v) if isinstance(v, list) else v))
if not self.silent:
click.echo("Processing %s (%s)" % (click.style(
self.name, fg="cyan", bold=True), "; ".join(env_dump)))
click.secho("-" * terminal_width, bold=True)
result = self._run_platform()
is_error = result['returncode'] != 0
if self.silent and not is_error:
return True
if is_error or CTX_META_TEST_IS_RUNNING not in self.cmd_ctx.meta:
print_header(
"[%s] Took %.2f seconds" %
((click.style("ERROR", fg="red", bold=True) if
is_error else click.style("SUCCESS", fg="green", bold=True)),
time() - start_time),
is_error=is_error)
return not is_error
def get_build_variables(self): def get_build_variables(self):
variables = {"pioenv": self.name, "project_config": self.config.path} variables = {"pioenv": self.name, "project_config": self.config.path}
@ -92,7 +53,7 @@ class EnvironmentProcessor(object):
return [t for t in self.targets] return [t for t in self.targets]
return self.config.get("env:" + self.name, "targets", []) return self.config.get("env:" + self.name, "targets", [])
def _run_platform(self): def process(self):
if "platform" not in self.options: if "platform" not in self.options:
raise exception.UndefinedEnvPlatform(self.name) raise exception.UndefinedEnvPlatform(self.name)
@ -113,5 +74,6 @@ class EnvironmentProcessor(object):
skip_default_package=True) skip_default_package=True)
p = PlatformFactory.newPlatform(self.options['platform']) p = PlatformFactory.newPlatform(self.options['platform'])
return p.run(build_vars, build_targets, self.silent, self.verbose, result = p.run(build_vars, build_targets, self.silent, self.verbose,
self.jobs) self.jobs)
return result['returncode'] == 0

View File

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
import click import click
from tabulate import tabulate
from platformio import app from platformio import app
from platformio.compat import string_types from platformio.compat import string_types
@ -26,17 +27,7 @@ def cli():
@cli.command("get", short_help="Get existing setting/-s") @cli.command("get", short_help="Get existing setting/-s")
@click.argument("name", required=False) @click.argument("name", required=False)
def settings_get(name): def settings_get(name):
tabular_data = []
list_tpl = u"{name:<40} {value:<35} {description}"
terminal_width, _ = click.get_terminal_size()
click.echo(
list_tpl.format(name=click.style("Name", fg="cyan"),
value=(click.style("Value", fg="green") +
click.style(" [Default]", fg="yellow")),
description="Description"))
click.echo("-" * terminal_width)
for _name, _data in sorted(app.DEFAULT_SETTINGS.items()): for _name, _data in sorted(app.DEFAULT_SETTINGS.items()):
if name and name != _name: if name and name != _name:
continue continue
@ -46,20 +37,19 @@ def settings_get(name):
if not isinstance(_value, string_types) else _value) if not isinstance(_value, string_types) else _value)
if isinstance(_value, bool): if isinstance(_value, bool):
_value_str = "Yes" if _value else "No" _value_str = "Yes" if _value else "No"
_value_str = click.style(_value_str, fg="green")
if _value != _data['value']: if _value != _data['value']:
_defvalue_str = str(_data['value']) _defvalue_str = str(_data['value'])
if isinstance(_data['value'], bool): if isinstance(_data['value'], bool):
_defvalue_str = "Yes" if _data['value'] else "No" _defvalue_str = "Yes" if _data['value'] else "No"
_value_str += click.style(" [%s]" % _defvalue_str, fg="yellow") _value_str += " [%s]" % _defvalue_str
else: _value_str = click.style(_value_str, fg="yellow")
_value_str += click.style(" ", fg="yellow")
click.echo( tabular_data.append((_name, _value_str, _data['description']))
list_tpl.format(name=click.style(_name, fg="cyan"),
value=_value_str, click.echo(
description=_data['description'])) tabulate(tabular_data,
headers=["Name", "Current value [Default]", "Description"]))
@cli.command("set", short_help="Set new value for the setting") @cli.command("set", short_help="Set new value for the setting")

View File

@ -20,9 +20,9 @@ from os.path import isdir, join
from time import time from time import time
import click import click
from tabulate import tabulate
from platformio import exception, fs from platformio import exception, fs, util
from platformio.commands.run.helpers import print_header
from platformio.commands.test.embedded import EmbeddedTestProcessor from platformio.commands.test.embedded import EmbeddedTestProcessor
from platformio.commands.test.native import NativeTestProcessor from platformio.commands.test.native import NativeTestProcessor
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
@ -87,12 +87,12 @@ def cli( # pylint: disable=redefined-builtin
config.validate(envs=environment) config.validate(envs=environment)
click.echo("Verbose mode can be enabled via `-v, --verbose` option") click.echo("Verbose mode can be enabled via `-v, --verbose` option")
click.echo("Collected %d items" % len(test_names)) click.secho("Collected %d items" % len(test_names), bold=True)
results = [] results = []
start_time = time()
default_envs = config.default_envs() default_envs = config.default_envs()
for testname in test_names: for testname in test_names:
for envname in config.envs(): for envname in config.envs():
section = "env:%s" % envname section = "env:%s" % envname
@ -114,9 +114,12 @@ def cli( # pylint: disable=redefined-builtin
for p in patterns['ignore']]), for p in patterns['ignore']]),
] ]
if any(skip_conditions): if any(skip_conditions):
results.append((None, testname, envname)) results.append({"env": envname, "test": testname})
continue continue
click.echo()
print_processing_header(testname, envname)
cls = (NativeTestProcessor cls = (NativeTestProcessor
if config.get(section, "platform") == "native" else if config.get(section, "platform") == "native" else
EmbeddedTestProcessor) EmbeddedTestProcessor)
@ -133,43 +136,24 @@ def cli( # pylint: disable=redefined-builtin
monitor_rts=monitor_rts, monitor_rts=monitor_rts,
monitor_dtr=monitor_dtr, monitor_dtr=monitor_dtr,
verbose=verbose)) verbose=verbose))
results.append((tp.process(), testname, envname)) result = {
"env": envname,
"test": testname,
"elapsed": time(),
"succeeded": tp.process()
}
result['elapsed'] = time() - result['elapsed']
results.append(result)
print_processing_footer(result)
if without_testing: if without_testing:
return return
passed_nums = 0 print_testing_summary(results)
failed_nums = 0
testname_max_len = max([len(r[1]) for r in results])
envname_max_len = max([len(click.style(r[2], fg="cyan")) for r in results])
print_header("[%s]" % click.style("TEST SUMMARY")) command_failed = any(r.get("succeeded") is False for r in results)
click.echo() if command_failed:
for result in results:
status, testname, envname = result
if status is False:
failed_nums += 1
status_str = click.style("FAILED", fg="red")
elif status is None:
status_str = click.style("IGNORED", fg="yellow")
else:
passed_nums += 1
status_str = click.style("PASSED", fg="green")
format_str = "test/{:<%d} > {:<%d}\t[{}]" % (testname_max_len,
envname_max_len)
click.echo(format_str.format(testname, click.style(envname, fg="cyan"),
status_str),
err=status is False)
print_header("%s%d passed in %.2f seconds" %
("%d failed, " % failed_nums if failed_nums else "",
passed_nums, time() - start_time),
is_error=failed_nums,
fg="red" if failed_nums else "green")
if failed_nums:
raise exception.ReturnErrorCode(1) raise exception.ReturnErrorCode(1)
@ -181,3 +165,58 @@ def get_test_names(test_dir):
if not names: if not names:
names = ["*"] names = ["*"]
return names return names
def print_processing_header(test, env):
click.echo("Processing %s in %s environment" % (click.style(
test, fg="yellow", bold=True), click.style(env, fg="cyan", bold=True)))
terminal_width, _ = click.get_terminal_size()
click.secho("-" * terminal_width, bold=True)
def print_processing_footer(result):
is_failed = not result.get("succeeded")
util.print_labeled_bar(
"[%s] Took %.2f seconds" %
((click.style("FAILED", fg="red", bold=True) if is_failed else
click.style("PASSED", fg="green", bold=True)), result['elapsed']),
is_error=is_failed)
def print_testing_summary(results):
click.echo()
# util.print_labeled_bar("SUMMARY")
tabular_data = []
succeeded_nums = 0
failed_nums = 0
elapsed = 0
for result in results:
elapsed += result.get("elapsed", 0)
if result.get("succeeded") is False:
failed_nums += 1
status_str = click.style("FAILED", fg="red")
elif result.get("succeeded") is None:
status_str = "IGNORED"
else:
succeeded_nums += 1
status_str = click.style("PASSED", fg="green")
tabular_data.append(
(result['test'], click.style(result['env'], fg="cyan"), status_str,
util.humanize_elapsed_time(result.get("elapsed"))))
click.echo(tabulate(tabular_data,
headers=[
click.style(s, bold=True)
for s in ("Test", "Environment", "Status", "Time")
]),
err=failed_nums)
util.print_labeled_bar(
"%s%d succeeded in %s" %
("%d failed, " % failed_nums if failed_nums else "", succeeded_nums,
util.humanize_elapsed_time(elapsed)),
is_error=failed_nums,
fg="red" if failed_nums else "green")

View File

@ -28,7 +28,7 @@ class EmbeddedTestProcessor(TestProcessorBase):
def process(self): def process(self):
if not self.options['without_building']: if not self.options['without_building']:
self.print_progress("Building... (1/3)") self.print_progress("Building...")
target = ["__test"] target = ["__test"]
if self.options['without_uploading']: if self.options['without_uploading']:
target.append("checkprogsize") target.append("checkprogsize")
@ -36,7 +36,7 @@ class EmbeddedTestProcessor(TestProcessorBase):
return False return False
if not self.options['without_uploading']: if not self.options['without_uploading']:
self.print_progress("Uploading... (2/3)") self.print_progress("Uploading...")
target = ["upload"] target = ["upload"]
if self.options['without_building']: if self.options['without_building']:
target.append("nobuild") target.append("nobuild")
@ -48,7 +48,7 @@ class EmbeddedTestProcessor(TestProcessorBase):
if self.options['without_testing']: if self.options['without_testing']:
return None return None
self.print_progress("Testing... (3/3)") self.print_progress("Testing...")
return self.run() return self.run()
def run(self): def run(self):

View File

@ -24,12 +24,12 @@ class NativeTestProcessor(TestProcessorBase):
def process(self): def process(self):
if not self.options['without_building']: if not self.options['without_building']:
self.print_progress("Building... (1/2)") self.print_progress("Building...")
if not self.build_or_upload(["__test"]): if not self.build_or_upload(["__test"]):
return False return False
if self.options['without_testing']: if self.options['without_testing']:
return None return None
self.print_progress("Testing... (2/2)") self.print_progress("Testing...")
return self.run() return self.run()
def run(self): def run(self):

View File

@ -20,7 +20,6 @@ from string import Template
import click import click
from platformio import exception from platformio import exception
from platformio.commands.run.helpers import print_header
from platformio.project.helpers import get_project_test_dir from platformio.project.helpers import get_project_test_dir
TRANSPORT_OPTIONS = { TRANSPORT_OPTIONS = {
@ -100,12 +99,8 @@ class TestProcessorBase(object):
def get_baudrate(self): def get_baudrate(self):
return int(self.env_options.get("test_speed", self.DEFAULT_BAUDRATE)) return int(self.env_options.get("test_speed", self.DEFAULT_BAUDRATE))
def print_progress(self, text, is_error=False): def print_progress(self, text):
click.echo() click.secho(text, bold=self.options.get("verbose"))
print_header("[test/%s > %s] %s" %
(click.style(self.test_name, fg="yellow"),
click.style(self.env_name, fg="cyan"), text),
is_error=is_error)
def build_or_upload(self, target): def build_or_upload(self, target):
if not self._outputcpp_generated: if not self._outputcpp_generated:
@ -115,9 +110,6 @@ class TestProcessorBase(object):
if self.test_name != "*": if self.test_name != "*":
self.cmd_ctx.meta[CTX_META_TEST_RUNNING_NAME] = self.test_name self.cmd_ctx.meta[CTX_META_TEST_RUNNING_NAME] = self.test_name
if not self.options['verbose']:
click.echo("Please wait...")
try: try:
from platformio.commands.run import cli as cmd_run from platformio.commands.run import cli as cmd_run
return self.cmd_ctx.invoke(cmd_run, return self.cmd_ctx.invoke(cmd_run,

View File

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
import json import json
import math
import os import os
import platform import platform
import re import re
@ -445,6 +446,31 @@ def merge_dicts(d1, d2, path=None):
return d1 return d1
def print_labeled_bar(label, is_error=False, fg=None):
terminal_width, _ = click.get_terminal_size()
width = len(click.unstyle(label))
half_line = "=" * int((terminal_width - width - 2) / 2)
click.secho("%s %s %s" % (half_line, label, half_line),
fg=fg,
err=is_error)
def humanize_elapsed_time(total):
total = total or 0
constants = ((3600 * 24, "day"), (3600, "hour"), (60, "minute"),
(1, "second"))
tokens = []
for coef, name in constants:
t = (math.floor if total > 60 else round)(total / coef)
if t == 0:
continue
tokens.append("%d %s%s" % (t, name, "s" if t > 1 else ""))
total -= t * coef
if len(tokens) > 1:
tokens[-1] = "and %s" % tokens[-1]
return ", ".join(tokens)
def get_original_version(version): def get_original_version(version):
if version.count(".") != 2: if version.count(".") != 2:
return None return None

View File

@ -23,7 +23,8 @@ install_requires = [
"colorama", "colorama",
"pyserial>=3,<4,!=3.3", "pyserial>=3,<4,!=3.3",
"requests>=2.4.0,<3", "requests>=2.4.0,<3",
"semantic_version>=2.5.0,<3" "semantic_version>=2.5.0,<3",
"tabulate>=0.8.3"
] ]
setup( setup(

View File

@ -26,5 +26,5 @@ def test_local_env():
]) ])
if result['returncode'] != 1: if result['returncode'] != 1:
pytest.fail(result) pytest.fail(result)
assert all([s in result['out'] assert all([s in result['err']
for s in ("PASSED", "IGNORED", "FAILED")]), result['out'] for s in ("PASSED", "IGNORED", "FAILED")]), result['out']