Comparing version
245
index.js
@@ -18,119 +18,146 @@ /* eslint camelcase: 0 */ // <-- Per Jupyter message spec | ||
// TODO: Launch a kernel | ||
// For now, rely on an argument for a kernel runtime | ||
const kernel = require(process.argv[2]); | ||
const temp = require('temp').track(); | ||
const imageToAscii = require('image-to-ascii'); | ||
const identity = uuid.v4(); | ||
// const iopub = enchannel.createIOPubSubject(identity, kernel); | ||
const shell = enchannel.createShellSubject(identity, kernel); | ||
// const control = enchannel.createControlSubject(identity, kernel); | ||
// const stdinChannel = enchannel.createStdinSubject(identity, kernel); | ||
const fs = require('fs'); | ||
const spawnteract = require('spawnteract'); | ||
function createMessage(session, msg_type) { | ||
const username = process.env.LOGNAME || process.env.USER || | ||
process.env.LNAME || process.env.USERNAME; | ||
return { | ||
header: { | ||
username, | ||
session, | ||
msg_type, | ||
msg_id: uuid.v4(), | ||
date: new Date(), | ||
version: '5.0', | ||
}, | ||
metadata: {}, | ||
parent_header: {}, | ||
content: {}, | ||
}; | ||
} | ||
const sessionID = uuid.v4(); | ||
function isChildMessage(msg) { | ||
return this.header.msg_id === msg.parent_header.msg_id; | ||
} | ||
function startREPL(langInfo) { | ||
const rl = readline.createInterface(process.stdin, process.stdout); | ||
const iopub = enchannel.createIOPubSubject(identity, kernel); | ||
marked.setOptions({ | ||
renderer: new TerminalRenderer(), | ||
}); | ||
rl.setPrompt(`ick${langInfo.file_extension}> `); | ||
rl.prompt(); | ||
rl.on('line', (line) => { | ||
const executeRequest = createMessage(sessionID, 'execute_request'); | ||
executeRequest.content = { | ||
code: line, | ||
silent: false, | ||
store_history: true, | ||
user_expressions: {}, | ||
allow_stdin: false, | ||
stop_on_error: false, | ||
function main(c) { | ||
const identity = uuid.v4(); | ||
// const iopub = enchannel.createIOPubSubject(identity, kernel); | ||
const shell = enchannel.createShellSubject(identity, c.config); | ||
// const control = enchannel.createControlSubject(identity, kernel); | ||
// const stdinChannel = enchannel.createStdinSubject(identity, kernel); | ||
function createMessage(session, msg_type) { | ||
const username = process.env.LOGNAME || process.env.USER || | ||
process.env.LNAME || process.env.USERNAME; | ||
return { | ||
header: { | ||
username, | ||
session, | ||
msg_type, | ||
msg_id: uuid.v4(), | ||
date: new Date(), | ||
version: '5.0', | ||
}, | ||
metadata: {}, | ||
parent_header: {}, | ||
content: {}, | ||
}; | ||
const childMessages = iopub.filter(isChildMessage.bind(executeRequest)) | ||
.publish() | ||
.refCount(); | ||
const displayData = childMessages | ||
.filter(msg => msg.header.msg_type === 'execute_result' || | ||
msg.header.msg_type === 'display_data') | ||
.filter(msg => msg.content) | ||
.map(msg => msg.content.data); | ||
const executeReply = childMessages | ||
.filter(msg => msg.header.msg_type === 'execute_reply') | ||
.map(msg => msg.content); | ||
const streamReply = childMessages | ||
.filter(msg => msg.header.msg_type === 'stream') | ||
.map(msg => msg.content); | ||
streamReply.subscribe(content => { | ||
switch(content.name) { | ||
case 'stdout': | ||
process.stdout.write(content.text); | ||
break; | ||
case 'stderr': | ||
process.stderr.write(content.text); | ||
break; | ||
} | ||
} | ||
const sessionID = uuid.v4(); | ||
function isChildMessage(msg) { | ||
return this.header.msg_id === msg.parent_header.msg_id; | ||
} | ||
function startREPL(langInfo) { | ||
const rl = readline.createInterface(process.stdin, process.stdout); | ||
const iopub = enchannel.createIOPubSubject(identity, c.config); | ||
marked.setOptions({ | ||
renderer: new TerminalRenderer(), | ||
}); | ||
displayData.subscribe(data => { | ||
if(data['text/markdown']) { | ||
console.log(marked(data['text/markdown'])); | ||
} | ||
else if(data['text/plain']) { | ||
console.log(data['text/plain']); | ||
} | ||
rl.setPrompt(`ick${langInfo.file_extension}> `); | ||
rl.prompt(); | ||
rl.on('line', (line) => { | ||
const executeRequest = createMessage(sessionID, 'execute_request'); | ||
executeRequest.content = { | ||
code: line, | ||
silent: false, | ||
store_history: true, | ||
user_expressions: {}, | ||
allow_stdin: false, | ||
stop_on_error: false, | ||
}; | ||
const childMessages = iopub.filter(isChildMessage.bind(executeRequest)) | ||
.publish() | ||
.refCount(); | ||
const displayData = childMessages | ||
.filter(msg => msg.header.msg_type === 'execute_result' || | ||
msg.header.msg_type === 'display_data') | ||
.filter(msg => msg.content) | ||
.map(msg => msg.content.data); | ||
const executeReply = childMessages | ||
.filter(msg => msg.header.msg_type === 'execute_reply') | ||
.map(msg => msg.content); | ||
const streamReply = childMessages | ||
.filter(msg => msg.header.msg_type === 'stream') | ||
.map(msg => msg.content); | ||
streamReply.subscribe(content => { | ||
switch(content.name) { | ||
case 'stdout': | ||
process.stdout.write(content.text); | ||
break; | ||
case 'stderr': | ||
process.stderr.write(content.text); | ||
break; | ||
} | ||
}); | ||
displayData.subscribe(data => { | ||
if(data['image/png']) { | ||
temp.open('ick-image', (err, info) => { | ||
if (err) { | ||
console.error(err); | ||
return; | ||
} | ||
const decodedData = new Buffer(data['image/png'], 'base64'); | ||
const writer = fs.createWriteStream(info.path); | ||
writer.end(decodedData); | ||
writer.on('finish', () => { | ||
imageToAscii(info.path, (imErr, converted) => { | ||
console.log(imErr || converted); | ||
}); | ||
}); | ||
}); | ||
} | ||
else if(data['text/markdown']) { | ||
console.log(marked(data['text/markdown'])); | ||
} | ||
else if(data['text/plain']) { | ||
console.log(data['text/plain']); | ||
} | ||
}); | ||
executeReply.subscribe(content => { | ||
rl.setPrompt(`ick${langInfo.file_extension}:${content.execution_count}> `); | ||
rl.prompt(); | ||
}); | ||
shell.send(executeRequest); | ||
}).on('close', () => { | ||
console.log('Have a great day!'); | ||
shell.close(); | ||
iopub.close(); | ||
process.stdin.destroy(); | ||
}); | ||
executeReply.subscribe(content => { | ||
rl.setPrompt(`ick${langInfo.file_extension}:${content.execution_count}> `); | ||
rl.prompt(); | ||
}); | ||
shell.send(executeRequest); | ||
}).on('close', () => { | ||
console.log('Have a great day!'); | ||
shell.close(); | ||
iopub.close(); | ||
process.stdin.destroy(); | ||
} | ||
const kernelInfoRequest = createMessage(sessionID, 'kernel_info_request'); | ||
const kernelReply = shell.filter(msg => msg.parent_header.msg_id === kernelInfoRequest.header.msg_id) | ||
.map(msg => msg.content); | ||
kernelReply.subscribe(content => { | ||
process.stdout.write(chalk.green(content.banner)); | ||
startREPL(content.language_info); | ||
}); | ||
shell.send(kernelInfoRequest); | ||
} | ||
const kernelInfoRequest = createMessage(sessionID, 'kernel_info_request'); | ||
const kernelReply = shell.filter(msg => msg.parent_header.msg_id === kernelInfoRequest.header.msg_id) | ||
.map(msg => msg.content); | ||
// TODO: Launch a kernel | ||
// For now, rely on an argument for a kernel runtime | ||
const kernelName = process.argv[2]; | ||
kernelReply.subscribe(content => { | ||
process.stdout.write(chalk.green(content.banner)); | ||
startREPL(content.language_info); | ||
}); | ||
shell.send(kernelInfoRequest); | ||
spawnteract.launch(kernelName).then(main) | ||
{ | ||
"name": "ick", | ||
"version": "0.0.3", | ||
"version": "0.1.0", | ||
"description": "Interactive Console Experiment", | ||
"main": "index.js", | ||
"bin": { | ||
"ick": "index.js" | ||
}, | ||
"scripts": { | ||
@@ -14,6 +17,9 @@ "test": "echo \"Error: no test specified\" && exit 1" | ||
"enchannel-zmq-backend": "^0.4.0", | ||
"image-to-ascii": "^2.3.1", | ||
"marked": "^0.3.5", | ||
"marked-terminal": "^1.6.1", | ||
"spawnteract": "0.0.4", | ||
"temp": "^0.8.3", | ||
"uuid": "^2.0.1" | ||
} | ||
} |
@@ -8,9 +8,35 @@ # Interactive Console Experiments | ||
## Development | ||
## Installation | ||
* Clone this repository | ||
* `npm install` | ||
* Install jupyter-console `pip install jupyter-console` | ||
* Launch `jupyter console` | ||
* Type `%connect_info` into your jupyter console, grab the path to the kernel-XXXX.json | ||
* Run `node index.js /path/to/your/kernel-XXXX.json` | ||
Make sure you have zmq headers for your platform, build tools, yada yada. | ||
(Editor's Note: Surely there's a more substantive way to express this.) | ||
``` | ||
npm install -g ick | ||
``` | ||
:warning: This is full of bugs! Files aren't cleaned up yet! :warning: | ||
## Running | ||
``` | ||
ick <kernelName> | ||
``` | ||
### Example | ||
``` | ||
$ ick python3 | ||
Python 3.5.1 (default, Dec 7 2015, 21:59:08) | ||
Type "copyright", "credits" or "license" for more information. | ||
IPython 4.0.0 -- An enhanced Interactive Python. | ||
? -> Introduction and overview of IPython's features. | ||
%quickref -> Quick reference. | ||
help -> Python's own help system. | ||
object? -> Details about 'object', use 'object??' for extra details. | ||
%guiref -> A brief reference about the graphical user interface. | ||
ick.py> 243 | ||
243 | ||
ick.py> | ||
``` |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
8801
22.88%134
20.72%42
162.5%8
60%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added