The code defines a function importNotebook
to import a notebook, which interprets the notebook using the interpret
function from the Core
module, and then makes a module based on the notebook's language.
npm run import -- "import notebook"
var path = require('path');
// TODO: combine with id2 from rpc and nicename from notebook export
// TODO: insert niceName and getExports here?
// must have a unique id for each unique cell so that
// individual cells can serve as modules as well as notebooks
// adding the cell id as a part of the filename
function getCellPath(cell) {
var question = cell.questions && cell.questions[0]
? (' aka ' + cell.questions[0].substr(0, 50))
: ''
return path.join(path.dirname(path.resolve(cell.filename)), cell.id) + question
}
const ACCUMULATOR = {
info: [],
error: [],
log: [],
}
const CONSOLE = {
info: function (...args) {
ACCUMULATOR.info.push(args.map(a => String(a)).join(' '))
console.info(...args)
},
error: function (...args) {
ACCUMULATOR.error.push(args.map(a => String(a)).join(' '))
console.error(...args)
},
log: function (...args) {
ACCUMULATOR.log.push(args.map(a => String(a)).join(' '))
console.log(...args)
},
}
// How to test if a notebook has already been imported
function importNotebook("notebook",
"ctx = {}") {
var {interpret, makeModule, makeESModule, makeDylib, makeDLL, makePythonModule} = require('../Core')
// accept all arguments as the list of queries
if(arguments.length > 2) {
notebook = Array.from(arguments)
if(typeof arugments[arguments.length - 1] === 'object'
&& !Array.isArray(arugments[arguments.length - 1])) {
notebook = notebook.slice(0, arguments.length - 1)
ctx = arugments[arguments.length - 1]
}
}
if (typeof notebook === 'undefined') {
return Promise.resolve({})
}
// TODO: move this sort of thing to cache
var cells = interpret(notebook)
if(typeof cells.code !== 'undefined') {
if(!cells.filename.includes('Core')) {
CONSOLE.log(`importing ${notebook} - 1 cell - ${cells.id}`)
}
if(cells.language == 'python') {
return makePythonModule(cells.source.join(''),
cells.id,
ctx)
} else
if(cells.language == 'csharp') {
return makeDLL(cells.source.join(''), cells.id)
} else
if(cells.language == 'c' || cells.language == 'cpp' || cells.language == 'objective-c') {
return makeDylib(cells.source.join(''), cells.id)
} else
if (!cells.filename.match(/Core\//gi) && !cells.filename.match(/cache/gi)
&& cells.source.join('').match(/^import\s|^export\s/gmi)
) {
CONSOLE.error('ES module matched')
return Promise.resolve(makeESModule(cells.source.join(''), cells.filename, ctx))
} else
return makeModule(cells.source.join(''),
getCellPath(cells),
ctx)
}
CONSOLE.log(`importing ${notebook} - ${cells.length} cells - ${cells.map(c => c.id)}`)
var package = {}
for(let i = 0; i < cells.length; i++) {
let result
if(cells.language == 'python') {
result = makePythonModule(cells[i].source.join(''),
cells[i].id,
ctx)
} else
if(cells[i].language == 'csharp') {
result = makeDLL(cells[i].source.join(''), cells[i].id)
} else
if(cells[i].language == 'c' || cells[i].language == 'cpp' || cells[i].language == 'objective-c') {
result = makeDylib(cells[i].source.join(''), cells[i].id)
} else
if (!cells[i].filename.match(/Core\//gi) && !cells[i].filename.match(/cache/gi)
&& cells[i].source.join('').match(/^import\s|^export\s/gi)
) {
result = Promise.resolve(makeESModule(cells[i].source.join(''), cells[i].filename, ctx))
} else
result = makeModule(cells[i].source.join(''),
getCellPath(cells[i]),
ctx)
if(typeof result === 'object') {
// TODO: handle promises and merge them if they are objects?
if(typeof result[Object.keys(result)[0]] === 'function') {
const func = result[Object.keys(result)[0]]
package[cells[i].id] = func
package[func.name] = func
}
Object.assign(package, result)
}
if (typeof result === 'function') {
package[cells[i].id] = result
package[result.name] = result
}
package[i] = result
Object.assign(ctx, package)
}
return package
}
module.exports.importNotebook = importNotebook;
module.exports.import = importNotebook;
module.exports.CONSOLE = CONSOLE
module.exports.ACCUMULATOR = ACCUMULATOR
const path = require('path');
const { interpret, makeModule, makeESModule, makeDylib, makeDLL, makePythonModule } = require('../Core');
class Accumulator {
constructor() {
this.info = [];
this.error = [];
this.log = [];
}
info(...args) {
this.info.push(args.map(a => String(a)).join(' '));
console.info(...args);
}
error(...args) {
this.error.push(args.map(a => String(a)).join(' '));
console.error(...args);
}
log(...args) {
this.log.push(args.map(a => String(a)).join(' '));
console.log(...args);
}
}
const console = new Accumulator();
const getCellPath = (cell) => {
const { questions, filename, id } = cell;
const question = questions && questions[0]? ` aka ${questions[0].substr(0, 50)}` : '';
return path.join(path.dirname(path.resolve(filename)), id) + question;
};
const isESModule = (source) => /^import\s|^export\s/gi.test(source.join(''));
const getModuleMaker = (language, makeDylib, makeDLL, makePythonModule) => {
switch (language) {
case 'csharp':
return makeDLL;
case 'c':
case 'cpp':
case 'objective-c':
return makeDylib;
case 'python':
return makePythonModule;
default:
return makeModule;
}
};
const importNotebook = async (notebook, ctx = {}) => {
if (arguments.length > 2) {
notebook = Array.from(arguments);
if (typeof notebook[notebook.length - 1] === 'object' &&!Array.isArray(notebook[notebook.length - 1])) {
notebook = notebook.slice(0, notebook.length - 1);
ctx = notebook[notebook.length - 1];
}
}
if (typeof notebook === 'undefined') {
return Promise.resolve({});
}
const cells = await interpret(notebook);
const package = {};
const moduleMakers = {};
for (const cell of cells) {
const { source, language, id, filename } = cell;
const { make } = getModuleMaker(language, makeDylib, makeDLL, makePythonModule);
if (isESModule(source)) {
await console.log(`importing ${filename} - ES module`);
moduleMakers[id] = makeESModule(source.join(''), filename, ctx);
} else {
await console.log(`importing ${filename} - ${cells.length} cell - ${id}`);
moduleMakers[id] = await make(source.join(''), getCellPath(cell), ctx);
}
Object.assign(package, moduleMakers[id]);
Object.assign(ctx, package);
}
return package;
};
module.exports = {
importNotebook,
console,
package: {}
};
Importing Modules and Functions
The code starts by importing the path
module and defining a function getCellPath
to construct a file path from a cell object.
var path = require('path');
function getCellPath(cell) {
//...
}
Defining Accumulator and Console Objects
It then defines two objects: ACCUMULATOR
and CONSOLE
. ACCUMULATOR
is an object that accumulates log messages, and CONSOLE
is an object that provides wrapper functions for console.log
, console.info
, and console.error
. These wrapper functions add log messages to the ACCUMULATOR
object.
const ACCUMULATOR = {
info: [],
error: [],
log: [],
}
const CONSOLE = {
info: function (...args) {
//...
},
error: function (...args) {
//...
},
log: function (...args) {
//...
},
}
Defining the ImportNotebook Function
The importNotebook
function is defined to import a notebook. It takes a notebook
parameter, which can be either a single value or an array of values, and an optional ctx
parameter.
function importNotebook(notebook, ctx = {}) {
//...
}
Interpreting and Making Modules
The function uses the interpret
function from the Core
module to interpret the notebook. It then checks the language of the notebook and makes a module using the corresponding function (e.g., makePythonModule
for Python notebooks).
var cells = interpret(notebook)
if (typeof cells.code!== 'undefined') {
if (!cells.filename.includes('Core')) {
CONSOLE.log(`importing ${notebook} - 1 cell - ${cells.id}`)
}
if (cells.language == 'python') {
return makePythonModule(cells.code, ctx)
}
}
Incomplete Documentation
The code snippet appears to be incomplete, as there are several TODO comments and some functions are not fully defined. Additionally, the importNotebook
function seems to return a Promise
, but it is not clear what the resolution value is.