@cocalc/project
Version:
CoCalc: project daemon
78 lines • 3.07 kB
JavaScript
;
/*
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.python_format = void 0;
const fs_1 = require("fs");
const tmp_1 = require("tmp");
const awaiting_1 = require("awaiting");
const child_process_1 = require("child_process");
function close(proc, cb) {
proc.on("close", (code) => cb(undefined, code));
}
// TODO: diversify this via options to support autopep8, black (requires python 3.6), and others...
function yapf(input_path) {
return (0, child_process_1.spawn)("yapf", ["-i", input_path]);
}
// from a full stacktrace, only show user the last line (encodes some reason and line number) ... everything else does not help.
function tail(str, lines = 4) {
if (str == null) {
return "Problem running formatter.";
}
else {
return (str
.trim()
.split(/\r?\n/)
.slice(-lines)
.filter((x) => x.trim().length > 0)
.join("\n") || "");
}
}
async function python_format(input, options, logger) {
// create input temp file
const input_path = await (0, awaiting_1.callback)(tmp_1.file);
try {
await (0, awaiting_1.callback)(fs_1.writeFile, input_path, input);
// spawn the python formatter
const util = options.util || "yapf";
if (util !== "yapf") {
throw new Error("This project only supports 'yapf' for formatting Python");
}
const py_formatter = yapf(input_path);
py_formatter.on("error", (err) => {
// ATTN do not throw an error here, because this is triggered by the subprocess!
logger.debug(`Formatting utility exited with error no ${err.errno}`);
});
// stdout/err capture
let stdout = "";
let stderr = "";
// read data as it is produced.
py_formatter.stdout.on("data", (data) => (stdout += data.toString()));
py_formatter.stderr.on("data", (data) => (stderr += data.toString()));
// wait for subprocess to close.
const code = await (0, awaiting_1.callback)(close, py_formatter);
// only last line
// stdout = last_line(stdout);
if (code) {
if (code === -2) {
// ENOENT
throw new Error(`Formatting utility "${util}" is not installed`);
}
stderr = tail(stderr);
const err_msg = `Python formatter "${util}" exited with code ${code}:\n${stdout}\n${stderr}`;
logger.debug(`format python error: ${err_msg}`);
throw new Error(err_msg);
}
// all fine, we read from the temp file
const output = await (0, awaiting_1.callback)(fs_1.readFile, input_path);
const s = output.toString("utf-8");
return s;
}
finally {
(0, fs_1.unlink)(input_path, () => { });
}
}
exports.python_format = python_format;
//# sourceMappingURL=python-format.js.map