@gracexwho/model-card-generator
Version:
Tool for generating model cards for Jupyter Notebook.
250 lines (242 loc) • 7.06 kB
text/typescript
import { SyntaxNode, Argument, Parameter } from './python-parser';
const comma = ', ';
// tslint:disable-next-line: max-func-body-length
function printTabbed(node: SyntaxNode, tabLevel: number): string {
const tabs = ' '.repeat(4 * tabLevel);
switch (node.type) {
case 'assert':
return tabs + 'assert ' + printNode(node.cond);
case 'assign':
return (
tabs +
commaSep(node.targets) +
' ' +
(node.op || '=') +
' ' +
commaSep(node.sources)
);
case 'binop':
return '(' + printNode(node.left) + node.op + printNode(node.right) + ')';
case 'break':
return tabs + 'break';
case 'call':
return printNode(node.func) + '(' + node.args.map(printArg) + ')';
case 'class':
return (
tabs +
'class ' +
node.name +
(node.extends ? '(' + commaSep(node.extends) + ')' : '') +
':' +
lines(node.code, tabLevel + 1)
);
case 'comp_for':
case 'comp_if':
case 'continue':
return tabs + 'continue';
case 'decorator':
return (
'@' +
node.decorator +
(node.args ? '(' + commaSep(node.args) + ')' : '')
);
case 'decorate':
return (
tabs +
lines(node.decorators, tabLevel) +
printTabbed(node.def, tabLevel)
);
case 'def':
return (
tabs +
'def ' +
node.name +
'(' +
node.params.map(printParam).join(comma) +
'):' +
lines(node.code, tabLevel + 1)
);
case 'dict':
return '{' + node.entries.map(e => e.k + ':' + e.v) + '}';
case 'dot':
return printNode(node.value) + '.' + node.name;
case 'else':
return tabs + 'else:' + lines(node.code, tabLevel + 1);
case 'for':
return (
tabs +
'for ' +
commaSep(node.target) +
' in ' +
commaSep(node.iter) +
':' +
lines(node.code, tabLevel + 1) +
(node.else ? lines(node.else, tabLevel + 1) : '')
);
case 'from':
return (
tabs +
'from ' +
node.base +
' import ' +
node.imports
.map(im => im.path + (im.name ? ' as ' + im.name : ''))
.join(comma)
);
case 'global':
if (typeof(node.names) == 'undefined' || typeof(node.names) == 'string') {
return tabs + 'global ' + node.names;
} else {
return tabs + 'global ' + node.names.join(comma);
}
case 'if':
return (
tabs +
'if ' +
printNode(node.cond) +
':' +
lines(node.code, tabLevel + 1) +
(node.elif
? node.elif.map(
elif =>
tabs +
'elif ' +
elif.cond +
':' +
lines(elif.code, tabLevel + 1)
)
: '') +
(node.else ? tabs + 'else:' + lines(node.else.code, tabLevel + 1) : '')
);
case 'ifexpr':
return (
printNode(node.then) +
' if ' +
printNode(node.test) +
' else ' +
printNode(node.else)
);
case 'import':
return (
tabs +
'import ' +
node.names
.map(n => n.path + (n.name ? ' as ' + n.name : ''))
.join(comma)
);
case 'index':
return printNode(node.value) + '[' + commaSep(node.args) + ']';
case 'lambda':
return (
'lambda ' +
node.args.map(printParam).join(comma) +
': ' +
printNode(node.code)
);
case 'list':
return '[' + node.items.map(item => printNode(item)).join(comma) + ']';
case 'literal':
return typeof node.value === 'string' && node.value.indexOf('\n') >= 0
? '""' + node.value + '""'
: node.value.toString();
case 'module':
return lines(node.code, tabLevel);
case 'name':
return node.id;
case 'nonlocal':
return tabs + 'nonlocal ' + node.names.join(comma);
case 'raise':
return tabs + 'raise ' + printNode(node.err);
case 'return':
return tabs + 'return ' + (node.values ? commaSep(node.values) : '');
case 'set':
return '{' + commaSep(node.entries) + '}';
case 'slice':
return (
(node.start ? printNode(node.start) : '') +
':' +
(node.stop ? printNode(node.stop) : '') +
(node.step ? ':' + printNode(node.step) : '')
);
case 'starred':
return '*' + printNode(node.value);
case 'try':
return (
tabs +
'try:' +
lines(node.code, tabLevel + 1) +
(node.excepts
? node.excepts.map(
ex =>
tabs +
'except ' +
(ex.cond
? printNode(ex.cond) + (ex.name ? ' as ' + ex.name : '')
: '') +
':' +
lines(ex.code, tabLevel + 1)
)
: '') +
(node.else ? tabs + 'else:' + lines(node.else, tabLevel + 1) : '') +
(node.finally
? tabs + 'finally:' + lines(node.finally, tabLevel + 1)
: '')
);
case 'tuple':
return '(' + commaSep(node.items) + ')';
case 'unop':
return node.op + '(' + printNode(node.operand) + ')';
case 'while':
return (
tabs +
'while ' +
printNode(node.cond) +
':' +
lines(node.code, tabLevel + 1)
);
case 'with':
return (
tabs +
'with ' +
node.items.map(w => w.with + (w.as ? ' as ' + w.as : '')).join(comma) +
':' +
lines(node.code, tabLevel + 1)
);
case 'yield':
return (
tabs +
'yield ' +
(node.from ? printNode(node.from) : '') +
(node.value ? commaSep(node.value) : '')
);
}
}
function printParam(param: Parameter): string {
return (
(param.star ? '*' : '') +
(param.starstar ? '**' : '') +
param.name +
(param.default_value ? '=' + printNode(param.default_value) : '') +
(param.anno ? printNode(param.anno) : '')
);
}
function printArg(arg: Argument): string {
return (
(arg.kwargs ? '**' : '') +
(arg.varargs ? '*' : '') +
(arg.keyword ? printNode(arg.keyword) + '=' : '') +
printNode(arg.actual) +
(arg.loop ? ' for ' + arg.loop.for + ' in ' + arg.loop.in : '')
);
}
function commaSep(items: SyntaxNode[]): string {
return items.map(printNode).join(comma);
}
function lines(items: SyntaxNode[], tabLevel: number): string {
return items
.map(i => printTabbed(i, tabLevel))
.join(tabLevel === 0 ? '\n\n' : '\n'); // seperate top-level definitons with an extra newline
}
export function printNode(node: SyntaxNode): string {
return printTabbed(node, 0);
}