@nteract/fs-kernels
Version:
A manager for the filesystem aspects of Juyter kernels
227 lines (226 loc) • 7.59 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const fs_1 = __importDefault(require("fs"));
const os_1 = require("os");
const path_1 = __importDefault(require("path"));
let sysPrefixGuess;
function home(subDir) {
const baseDir = os_1.homedir();
return subDir ? path_1.default.join(baseDir, subDir) : baseDir;
}
function pushIfExists(paths, pathToPush) {
if (fs_1.default.existsSync(pathToPush)) {
paths.push(pathToPush);
}
}
function accessCheck(d) {
// check if a directory exists and is listable (X_OK)
if (!fs_1.default.existsSync(d)) {
return false;
}
try {
fs_1.default.accessSync(d, fs_1.default.constants.X_OK);
}
catch (e) {
// [WSA]EACCES
return false;
}
return true;
}
function guessSysPrefix() {
// inexpensive guess for sysPrefix based on location of `which python`
// based on shutil.which from Python 3.5
// only run once:
if (sysPrefixGuess !== undefined) {
return sysPrefixGuess;
}
const PATH = (process.env.PATH || "").split(path_1.default.delimiter);
if (PATH.length === 0) {
sysPrefixGuess = null;
return;
}
let pathext = [""];
if (process.platform === "win32") {
pathext = (process.env.PATHEXT || "").split(path_1.default.delimiter);
}
PATH.some(bin => {
bin = path_1.default.resolve(bin);
const python = path_1.default.join(bin, "python");
return pathext.some((ext) => {
const exe = python + ext;
if (accessCheck(exe)) {
// PREFIX/bin/python exists, return PREFIX
// following symlinks
if (process.platform === "win32") {
// Windows: Prefix\Python.exe
sysPrefixGuess = path_1.default.dirname(fs_1.default.realpathSync(exe));
}
else {
// Everywhere else: prefix/bin/python
sysPrefixGuess = path_1.default.dirname(path_1.default.dirname(fs_1.default.realpathSync(exe)));
}
return true;
}
return false;
});
});
if (sysPrefixGuess === undefined) {
// store null as nothing found, but don't run again
sysPrefixGuess = null;
}
return sysPrefixGuess;
}
let askJupyterPromise = null;
function askJupyter() {
// ask Jupyter where the paths are
if (!askJupyterPromise) {
askJupyterPromise = new Promise((resolve, reject) => {
child_process_1.exec("python3 -m jupyter --paths --json", (err, stdout) => {
if (err) {
reject(err);
}
else {
resolve(JSON.parse(stdout.toString().trim()));
}
});
});
}
return askJupyterPromise;
}
function systemConfigDirs() {
const paths = [];
// System wide for Windows and Unix
if (process.platform === "win32") {
const defaultProgramDataPath = "C:\\ProgramData";
pushIfExists(paths, path_1.default.resolve(path_1.default.join(process.env.PROGRAMDATA || defaultProgramDataPath, "jupyter")));
}
else {
pushIfExists(paths, "/usr/local/etc/jupyter");
pushIfExists(paths, "/etc/jupyter");
}
return paths;
}
async function configDirs(opts) {
if (opts && opts.askJupyter) {
try {
const configPaths = await askJupyter();
return configPaths.config.filter(fs_1.default.existsSync);
}
catch (_a) {
return configDirs();
}
}
const paths = [];
if (process.env.JUPYTER_CONFIG_DIR) {
pushIfExists(paths, process.env.JUPYTER_CONFIG_DIR);
}
pushIfExists(paths, home(".jupyter"));
const systemDirs = systemConfigDirs();
if (opts && opts.withSysPrefix) {
return new Promise((resolve, reject) => {
// deprecated: withSysPrefix expects a Promise
// but no change in content
resolve(configDirs());
});
}
// inexpensive guess, based on location of `python` executable
const sysPrefix = guessSysPrefix() || "/usr/local/";
const sysPathed = path_1.default.join(sysPrefix, "etc", "jupyter");
if (systemDirs.indexOf(sysPathed) === -1) {
pushIfExists(paths, sysPathed);
}
return paths.concat(systemDirs);
}
function systemDataDirs() {
const paths = [];
// System wide for Windows and Unix
if (process.platform === "win32") {
const defaultProgramDataPath = "C:\\ProgramData";
pushIfExists(paths, path_1.default.resolve(path_1.default.join(process.env.PROGRAMDATA || defaultProgramDataPath, "jupyter")));
}
else {
pushIfExists(paths, "/usr/local/share/jupyter");
pushIfExists(paths, "/usr/share/jupyter");
}
return paths;
}
/**
* where the userland data directory resides
* includes things like the runtime files
* @return directory for data
*/
function userDataDir() {
// Userland specific
if (process.platform === "darwin") {
return home("Library/Jupyter");
}
else if (process.platform === "win32") {
const defaultAppDataPath = home("AppData");
return path_1.default.resolve(path_1.default.join(process.env.APPDATA || defaultAppDataPath, "jupyter"));
}
return process.env.XDG_DATA_HOME || home(".local/share/jupyter");
}
/**
* dataDirs returns all the expected static directories for this OS.
* The user of this function should make sure to make sure the directories
* exist.
*
* When withSysPrefix is set, this returns a promise of directories
*
* @param withSysPrefix include the sys.prefix paths
* @return All the Jupyter Data Dirs
*/
async function dataDirs(opts) {
if (opts && opts.askJupyter) {
try {
const dataPaths = await askJupyter();
return dataPaths.data.filter(fs_1.default.existsSync);
}
catch (error) {
return dataDirs();
}
}
const paths = [];
if (process.env.JUPYTER_PATH) {
pushIfExists(paths, process.env.JUPYTER_PATH);
}
pushIfExists(paths, userDataDir());
const systemDirs = systemDataDirs();
if (opts && opts.withSysPrefix) {
// deprecated: withSysPrefix expects a Promise
// but no change in content
return await (async () => dataDirs())();
}
// inexpensive guess, based on location of `python` executable
const sysPrefix = guessSysPrefix();
if (sysPrefix) {
const sysPathed = path_1.default.join(sysPrefix, "share", "jupyter");
if (systemDirs.indexOf(sysPathed) === -1) {
pushIfExists(paths, sysPathed);
}
}
return paths.concat(systemDirs);
}
async function runtimeDir(opts) {
if (opts && opts.askJupyter) {
try {
const paths = await askJupyter();
return paths.runtime;
}
catch (error) {
return runtimeDir();
}
}
if (process.env.JUPYTER_RUNTIME_DIR) {
return process.env.JUPYTER_RUNTIME_DIR;
}
if (process.env.XDG_RUNTIME_DIR) {
return path_1.default.join(process.env.XDG_RUNTIME_DIR, "jupyter");
}
return path_1.default.join(userDataDir(), "runtime");
}
exports.default = { dataDirs, runtimeDir, configDirs, guessSysPrefix };