Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/util/opts.js
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45//##############################################################################6//7// CoCalc: Collaborative web-based calculation8// Copyright (C) 2017, Sagemath Inc.9// MS-RSL10//11//##############################################################################1213/*14Handling of input opts to functions and type checking.15*/1617let DEBUG, TEST_MODE, val;18const PropTypes = require("prop-types");1920const immutable_types = require("./immutable-types");2122/*23Testing related env/DEVEL/DEBUG stuff24*/2526if (27__guard__(28typeof process !== "undefined" && process !== null29? process.env30: undefined,31(x) => x.DEVEL,32) &&33!__guard__(34typeof process !== "undefined" && process !== null35? process.env36: undefined,37(x1) => x1.SMC_TEST,38)39) {40// Running on node and DEVEL is set and not running under test suite41DEBUG = true;42} else {43DEBUG = false;44}4546// console.debug only logs if DEBUG is true47if (DEBUG) {48console.debug = console.log;49} else {50console.debug = function () {};51}5253if (54__guard__(55typeof process !== "undefined" && process !== null56? process.env57: undefined,58(x2) => x2.SMC_TEST,59)60) {61// in test mode we *do* want exception to get thrown below when type checks fails62TEST_MODE = true;63}6465// Checks property types on a target object with checkers in a declaration.66// Declarations should throw an Error for mismatches and undefined if OK.67const types = (exports.types = function (68target,69declaration,70identifier = "check.types",71) {72if (identifier == null) {73identifier = "check.types";74}75if (typeof target !== "object") {76throw new Error("Types was given a non-object to check");77}7879if (typeof declaration !== "object") {80throw new Error(81`Types was given a ${typeof declaration} as a declaration instead of an object`,82);83}8485return PropTypes.checkPropTypes(86declaration,87target,88"checking a",89identifier,90);91});9293for (let key in PropTypes) {94val = PropTypes[key];95if (key !== "checkPropTypes" && key !== "PropTypes") {96types[key] = val;97}98}99100types.immutable = immutable_types.immutable;101102// Returns a new object with properties determined by those of obj1 and103// obj2. The properties in obj1 *must* all also appear in obj2. If an104// obj2 property has value "defaults.required", then it must appear in105// obj1. For each property P of obj2 not specified in obj1, the106// corresponding value obj1[P] is set (all in a new copy of obj1) to107// be obj2[P].108exports.defaults = function (obj1, obj2, allow_extra = false, strict = false) {109let err;110if (strict == null) {111strict = false;112}113if (obj1 == null) {114obj1 = {};115}116const error = function () {117try {118return `(obj1=${exports.trunc(119exports.to_json(obj1),1201024,121)}, obj2=${exports.trunc(exports.to_json(obj2), 1024)})`;122} catch (err) {123return "";124}125};126if (obj1 == null) {127// useful special case128obj1 = {};129}130if (typeof obj1 !== "object") {131// We put explicit traces before the errors in this function,132// since otherwise they can be very hard to debug.133err = `BUG -- Traceback -- misc.defaults -- TypeError: function takes inputs as an object ${error()}`;134if (strict || DEBUG || TEST_MODE) {135throw new Error(err);136} else {137console.log(err);138console.trace();139return obj2;140}141}142const r = {};143for (var prop in obj2) {144val = obj2[prop];145if (obj1.hasOwnProperty(prop) && obj1[prop] != null) {146if (obj2[prop] === exports.defaults.required && obj1[prop] == null) {147err = `misc.defaults -- TypeError: property '${prop}' must be specified: ${error()}`;148if (strict || DEBUG || TEST_MODE) {149throw new Error(err);150} else {151console.warn(err);152console.trace();153}154}155r[prop] = obj1[prop];156} else if (obj2[prop] != null) {157// only record not undefined properties158if (obj2[prop] === exports.defaults.required) {159err = `misc.defaults -- TypeError: property '${prop}' must be specified: ${error()}`;160if (strict || DEBUG || TEST_MODE) {161throw new Error(err);162} else {163console.warn(err);164console.trace();165}166} else {167r[prop] = obj2[prop];168}169}170}171if (!allow_extra) {172for (prop in obj1) {173val = obj1[prop];174if (!obj2.hasOwnProperty(prop)) {175err = `misc.defaults -- TypeError: got an unexpected argument '${prop}' ${error()}`;176console.trace();177if (strict || DEBUG || TEST_MODE) {178throw new Error(err);179} else {180console.warn(err);181}182}183}184}185return r;186};187188// WARNING -- don't accidentally use this as a default:189const required =190(exports.required =191exports.defaults.required =192"__!!!!!!this is a required property!!!!!!__");193194function __guard__(value, transform) {195return typeof value !== "undefined" && value !== null196? transform(value)197: undefined;198}199200201