Skip to content

Commit

Permalink
Fixed an issue with PIO Home's "No JSON object could be decoded" // R…
Browse files Browse the repository at this point in the history
…esolve #2823
  • Loading branch information
ivankravets committed Aug 15, 2019
1 parent 59114bb commit 3edf7e6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 28 deletions.
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ PlatformIO 4.0
* Renamed "enable_ssl" setting to `strict_ssl <http://docs.platformio.org/page/userguide/cmd_settings.html#strict-ssl>`__
* Fixed an issue with incorrect escaping of Windows slashes when using `PIO Unified Debugger <http://docs.platformio.org/page/plus/debugging.html>`__ and "piped" openOCD
* Fixed an issue when "debug", "home", "run", and "test" commands were not shown in "platformio --help" CLI
* Fixed an issue with PIO Home's "No JSON object could be decoded" (`issue #2823 <https://github.com/platformio/platformio-core/issues/2823>`_)

4.0.0 (2019-07-10)
~~~~~~~~~~~~~~~~~~
Expand Down
76 changes: 48 additions & 28 deletions platformio/commands/home/rpc/handlers/piocore.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import click
import jsonrpc # pylint: disable=import-error
from twisted.internet import defer # pylint: disable=import-error
from twisted.internet import threads # pylint: disable=import-error
from twisted.internet import utils # pylint: disable=import-error

Expand Down Expand Up @@ -68,6 +69,10 @@ def get_value_and_reset(self):

class PIOCoreRPC(object):

@staticmethod
def version():
return __version__

@staticmethod
def setup_multithreading_std_streams():
if isinstance(sys.stdout, MultiThreadingStdStream):
Expand All @@ -79,41 +84,67 @@ def setup_multithreading_std_streams():

@staticmethod
def call(args, options=None):
PIOCoreRPC.setup_multithreading_std_streams()
cwd = (options or {}).get("cwd") or os.getcwd()
return defer.maybeDeferred(PIOCoreRPC._call_generator, args, options)

@staticmethod
@defer.inlineCallbacks
def _call_generator(args, options=None):
for i, arg in enumerate(args):
if isinstance(arg, string_types):
args[i] = arg.encode(get_filesystem_encoding()) if PY2 else arg
else:
args[i] = str(arg)

def _call_inline():
to_json = "--json-output" in args

try:
if args and args[0] in ("account", "remote"):
result = yield PIOCoreRPC._call_subprocess(args, options)
defer.returnValue(PIOCoreRPC._process_result(result, to_json))
else:
result = yield PIOCoreRPC._call_inline(args, options)
try:
defer.returnValue(
PIOCoreRPC._process_result(result, to_json))
except ValueError:
# fall-back to subprocess method
result = yield PIOCoreRPC._call_subprocess(args, options)
defer.returnValue(
PIOCoreRPC._process_result(result, to_json))
except Exception as e: # pylint: disable=bare-except
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4003, message="PIO Core Call Error", data=str(e))

@staticmethod
def _call_inline(args, options):
PIOCoreRPC.setup_multithreading_std_streams()
cwd = (options or {}).get("cwd") or os.getcwd()

def _thread_task():
with fs.cd(cwd):
exit_code = __main__.main(["-c"] + args)
return (PIOCoreRPC.thread_stdout.get_value_and_reset(),
PIOCoreRPC.thread_stderr.get_value_and_reset(), exit_code)

if args and args[0] in ("account", "remote"):
d = utils.getProcessOutputAndValue(
helpers.get_core_fullpath(),
args,
path=cwd,
env={k: v
for k, v in os.environ.items() if "%" not in k})
else:
d = threads.deferToThread(_call_inline)
return threads.deferToThread(_thread_task)

d.addCallback(PIOCoreRPC._call_callback, "--json-output" in args)
d.addErrback(PIOCoreRPC._call_errback)
return d
@staticmethod
def _call_subprocess(args, options):
cwd = (options or {}).get("cwd") or os.getcwd()
return utils.getProcessOutputAndValue(
helpers.get_core_fullpath(),
args,
path=cwd,
env={k: v
for k, v in os.environ.items() if "%" not in k})

@staticmethod
def _call_callback(result, json_output=False):
def _process_result(result, to_json=False):
out, err, code = result
text = ("%s\n\n%s" % (out, err)).strip()
if code != 0:
raise Exception(text)
if not json_output:
if not to_json:
return text
try:
return json.loads(out)
Expand All @@ -129,14 +160,3 @@ def _call_callback(result, json_output=False):
except ValueError:
pass
raise e

@staticmethod
def _call_errback(failure):
raise jsonrpc.exceptions.JSONRPCDispatchException(
code=4003,
message="PIO Core Call Error",
data=failure.getErrorMessage())

@staticmethod
def version():
return __version__

0 comments on commit 3edf7e6

Please sign in to comment.