@amplitude/ampli
Version:
Amplitude CLI
74 lines (73 loc) • 3.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const base_1 = require("../base");
const toInt = (i) => parseInt(i, 10) || 0;
class PythonVerifier extends base_1.Verifier {
constructor(ampliInstanceNames = ['itly']) {
super('py', ampliInstanceNames);
this.ampliInstanceNames = ampliInstanceNames;
this.getReferenceName = (eventName) => lodash_1.snakeCase(eventName);
}
static createInstanceNameRegex(instanceName) {
const nameParts = instanceName.split('.');
const result = [];
for (let i = nameParts.length - 1; i >= 0; i -= 1) {
result.push(i > 0 ? `value=Attribute\\(` : `value=Name\\(`);
}
for (let i = 0; i < nameParts.length; i += 1) {
result.push(i === 0
? `id='${nameParts[i]}', ctx=Load\\(\\), lineno=(\\d+), col_offset=(\\d+)[^)]*\\)`
: `attr='${nameParts[i]}', ctx=Load\\(\\)[^)]*\\)`);
if (i < nameParts.length - 1) {
result.push(', ');
}
}
return `(?:${result.join('')})`;
}
static createRegex(instanceName) {
return new RegExp(`Expr\\(value=Call\\(func=Attribute\\(${PythonVerifier.createInstanceNameRegex(instanceName)}, attr='([^']+)'`, 'g');
}
static createTrackRegex(instanceName) {
return new RegExp(`Expr\\(value=Call\\(func=Attribute\\(${PythonVerifier.createInstanceNameRegex(instanceName)}, attr='track', ctx=Load\\(\\), lineno=\\d+, col_offset=\\d+[^)]*\\), args=\\[(.*?)]`, 'g');
}
static createEventClassByAttrRegex(instanceName) {
return new RegExp(`, Call\\(func=Attribute\\(value=Name\\(id='${PythonVerifier.createInstanceNameRegex(instanceName)}', ctx=Load\\(\\), lineno=\\d+, col_offset=\\d+[^)]*\\), attr='([^']+)'`, 'g');
}
checkDependencies() {
super.checkDependencies();
this.execSyncToString(`python3 --version`);
}
async doVerify(eventNames, workingDirs) {
return this.verifyEach((filePath, _, addReference) => {
const script = `import ast; print(ast.dump(ast.parse(open("${filePath}").read()), True, True))`;
const command = `python3 -c '${script}'`;
const stdout = this.execSyncToString(command);
this.ampliInstanceNames.forEach(instanceName => {
const regex = PythonVerifier.createRegex(instanceName);
const trackRegex = PythonVerifier.createTrackRegex(instanceName);
const eventClassByAttrRegex = PythonVerifier.createEventClassByAttrRegex(instanceName);
let trackMatch = trackRegex.exec(stdout);
while (trackMatch != null) {
const [match, row, column] = trackMatch;
const eventClassNameMatch = PythonVerifier.eventClassByName.exec(match);
const eventClassAttrMatch = eventClassByAttrRegex.exec(match);
[eventClassNameMatch, eventClassAttrMatch].filter((m) => !!m).forEach(m => {
const [, eventClassName] = m;
const name = lodash_1.snakeCase(eventClassName);
addReference({ filePath, name, row: toInt(row), column: toInt(column) });
});
trackMatch = trackRegex.exec(stdout);
}
let match = regex.exec(stdout);
while (match != null) {
const [, row, column, name] = match;
addReference({ filePath, name, row: toInt(row), column: toInt(column) });
match = regex.exec(stdout);
}
});
}, workingDirs);
}
}
exports.default = PythonVerifier;
PythonVerifier.eventClassByName = /\bCall\(func=Name\(id='([^']+)'/;