From dfca7f0b6877e9f3fe06920e9276339a778c8fd6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 1 Jul 2019 15:55:42 +0300 Subject: [PATCH] Speedup PIO Home via internal calling of PIO Core CLI --- platformio/__main__.py | 3 +- platformio/commands/debug/command.py | 2 +- platformio/commands/debug/helpers.py | 12 -------- platformio/commands/home/rpc/handlers/os.py | 9 +++--- .../commands/home/rpc/handlers/piocore.py | 28 +++++++++++-------- platformio/commands/platform.py | 2 +- platformio/compat.py | 4 +++ platformio/util.py | 12 ++++++++ 8 files changed, 41 insertions(+), 31 deletions(-) diff --git a/platformio/__main__.py b/platformio/__main__.py index 8b1ab093..d4664935 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -119,8 +119,7 @@ An unexpected error occurred. Further steps: def debug_gdb_main(): - sys.argv = [sys.argv[0], "debug", "--interface", "gdb"] + sys.argv[1:] - return main() + return main([sys.argv[0], "debug", "--interface", "gdb"] + sys.argv[1:]) if __name__ == "__main__": diff --git a/platformio/commands/debug/command.py b/platformio/commands/debug/command.py index 7892cfee..8599a962 100644 --- a/platformio/commands/debug/command.py +++ b/platformio/commands/debug/command.py @@ -123,7 +123,7 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, if helpers.is_mi_mode(__unprocessed): click.echo('~"Preparing firmware for debugging...\\n"') output = helpers.GDBBytesIO() - with helpers.capture_std_streams(output): + with util.capture_std_streams(output): helpers.predebug_project(ctx, project_dir, env_name, preload, verbose) output.close() diff --git a/platformio/commands/debug/helpers.py b/platformio/commands/debug/helpers.py index ddc9db97..daaa8d93 100644 --- a/platformio/commands/debug/helpers.py +++ b/platformio/commands/debug/helpers.py @@ -14,7 +14,6 @@ import sys import time -from contextlib import contextmanager from fnmatch import fnmatch from hashlib import sha1 from io import BytesIO @@ -41,17 +40,6 @@ class GDBBytesIO(BytesIO): # pylint: disable=too-few-public-methods self.STDOUT.flush() -@contextmanager -def capture_std_streams(stdout, stderr=None): - _stdout = sys.stdout - _stderr = sys.stderr - sys.stdout = stdout - sys.stderr = stderr or stdout - yield - sys.stdout = _stdout - sys.stderr = _stderr - - def is_mi_mode(args): return "--interpreter" in " ".join(args) diff --git a/platformio/commands/home/rpc/handlers/os.py b/platformio/commands/home/rpc/handlers/os.py index afb2e29f..c84f486e 100644 --- a/platformio/commands/home/rpc/handlers/os.py +++ b/platformio/commands/home/rpc/handlers/os.py @@ -14,6 +14,7 @@ from __future__ import absolute_import +import codecs import glob import os import shutil @@ -67,10 +68,10 @@ class OSRPC(object): def request_content(self, uri, data=None, headers=None, cache_valid=None): if uri.startswith('http'): return self.fetch_content(uri, data, headers, cache_valid) - if isfile(uri): - with open(uri) as fp: - return fp.read() - return None + if not isfile(uri): + return None + with codecs.open(uri, encoding="utf-8") as fp: + return fp.read() @staticmethod def open_url(url): diff --git a/platformio/commands/home/rpc/handlers/piocore.py b/platformio/commands/home/rpc/handlers/piocore.py index 198552d1..19d7d370 100644 --- a/platformio/commands/home/rpc/handlers/piocore.py +++ b/platformio/commands/home/rpc/handlers/piocore.py @@ -17,12 +17,12 @@ from __future__ import absolute_import import json import os import re +from io import BytesIO import jsonrpc # pylint: disable=import-error -from twisted.internet import utils # pylint: disable=import-error +from twisted.internet import threads # pylint: disable=import-error -from platformio import __version__ -from platformio.commands.home import helpers +from platformio import __main__, __version__, util from platformio.compat import string_types @@ -30,7 +30,6 @@ class PIOCoreRPC(object): @staticmethod def call(args, options=None): - json_output = "--json-output" in args try: args = [ str(arg) if not isinstance(arg, string_types) else arg @@ -39,13 +38,20 @@ class PIOCoreRPC(object): except UnicodeError: raise jsonrpc.exceptions.JSONRPCDispatchException( code=4002, message="PIO Core: non-ASCII chars in arguments") - d = utils.getProcessOutputAndValue( - helpers.get_core_fullpath(), - args, - path=(options or {}).get("cwd"), - env={k: v - for k, v in os.environ.items() if "%" not in k}) - d.addCallback(PIOCoreRPC._call_callback, json_output) + + def _call_cli(): + outbuff = BytesIO() + errbuff = BytesIO() + with util.capture_std_streams(outbuff, errbuff): + with util.cd((options or {}).get("cwd") or os.getcwd()): + exit_code = __main__.main(["-c"] + args) + result = (outbuff.getvalue(), errbuff.getvalue(), exit_code) + outbuff.close() + errbuff.close() + return result + + d = threads.deferToThread(_call_cli) + d.addCallback(PIOCoreRPC._call_callback, "--json-output" in args) d.addErrback(PIOCoreRPC._call_errback) return d diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 5b35c4df..26f86666 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -182,7 +182,7 @@ def platform_frameworks(query, json_output): for framework in util.get_api_result("/frameworks", cache_valid="7d"): if query == "all": query = "" - search_data = dump_json_to_unicode(framework) + search_data = framework if query and query.lower() not in search_data.lower(): continue framework['homepage'] = ("https://platformio.org/frameworks/" + diff --git a/platformio/compat.py b/platformio/compat.py index 4aad4ea2..686518a8 100644 --- a/platformio/compat.py +++ b/platformio/compat.py @@ -54,6 +54,8 @@ if PY2: return data def dump_json_to_unicode(obj): + if isinstance(obj, unicode): + return obj return json.dumps(obj, encoding=get_filesystem_encoding(), ensure_ascii=False).encode("utf8") @@ -100,4 +102,6 @@ else: return data.encode() def dump_json_to_unicode(obj): + if isinstance(obj, string_types): + return obj return json.dumps(obj, ensure_ascii=False) diff --git a/platformio/util.py b/platformio/util.py index b93b4d8a..377160b1 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -20,6 +20,7 @@ import socket import stat import sys import time +from contextlib import contextmanager from functools import wraps from glob import glob from os.path import abspath, basename, dirname, isfile, join @@ -107,6 +108,17 @@ def singleton(cls): return get_instance +@contextmanager +def capture_std_streams(stdout, stderr=None): + _stdout = sys.stdout + _stderr = sys.stderr + sys.stdout = stdout + sys.stderr = stderr or stdout + yield + sys.stdout = _stdout + sys.stderr = _stderr + + def load_json(file_path): try: with open(file_path, "r") as f: