from __future__ import unicode_literals
from codeop import Compile
import os
import sys
import json
import traceback
import platform
import struct
import math
NODE_CHANNEL_FD = int(os.environ['NODE_CHANNEL_FD'])
UNICODE_TYPE = unicode if sys.version_info[0] == 2 else str
if sys.version_info[0] <= 2:
# print('PY2')
def _exec(_code_, _globs_):
exec('exec _code_ in _globs_')
else:
_exec = getattr(__builtins__, 'exec')
_locals = {'__name__': '__console__', '__doc__': None}
_compile = Compile()
if platform.system() == 'Windows':
# hacky reimplementation of https://github.com/nodejs/node/blob/master/deps/uv/src/win/pipe.c
def read_data(f):
header = f.read(16)
if not header:
return header
try:
msg_length, = struct.unpack(' 0 else '-Infinity'
return o.__dict__
if __name__ == '__main__':
writer = os.fdopen(NODE_CHANNEL_FD, 'wb')
reader = os.fdopen(NODE_CHANNEL_FD, 'rb')
while True:
try:
# Read new command
line = read_data(reader)
if not line:
break
try:
data = json.loads(line.decode('utf-8'))
except ValueError:
raise ValueError('Could not decode IPC data:\n{}'.format(repr(line)))
# Assert data saneness
if data['type'] not in ['execute', 'evaluate']:
raise Exception('Python bridge call `type` must be `execute` or `evaluate`')
if not isinstance(data['code'], UNICODE_TYPE):
raise Exception('Python bridge call `code` must be a string.')
# Run Python code
if data['type'] == 'execute':
_exec(_compile(data['code'], '', 'exec'), _locals)
response = dict(type='success')
else:
value = eval(_compile(data['code'], '', 'eval'), _locals)
response = dict(type='success', value=json.dumps(value, separators=(',', ':'), cls=JavaScriptEncoder))
except:
t, e, tb = sys.exc_info()
response = dict(type='exception', value=format_exception(t, e, tb))
data = json.dumps(response, separators=(',', ':')).encode('utf-8') + b'\n'
write_data(writer, data)
# Closing is messy
try:
reader.close()
except IOError:
pass
try:
writer.close()
except IOError:
pass