Mise à jour de Monitor.py et autres scripts
This commit is contained in:
230
myenv/lib/python3.11/site-packages/altair/jupyter/js/index.js
Normal file
230
myenv/lib/python3.11/site-packages/altair/jupyter/js/index.js
Normal file
@@ -0,0 +1,230 @@
|
||||
import vegaEmbed from "https://esm.sh/vega-embed@6?deps=vega@5&deps=vega-lite@5.20.1";
|
||||
import lodashDebounce from "https://esm.sh/lodash-es@4.17.21/debounce";
|
||||
|
||||
// Note: For offline support, the import lines above are removed and the remaining script
|
||||
// is bundled using vl-convert's javascript_bundle function. See the documentation of
|
||||
// the javascript_bundle function for details on the available imports and their names.
|
||||
// If an additional import is required in the future, it will need to be added to vl-convert
|
||||
// in order to preserve offline support.
|
||||
async function render({ model, el }) {
|
||||
let finalize;
|
||||
|
||||
function showError(error){
|
||||
el.innerHTML = (
|
||||
'<div style="color:red;">'
|
||||
+ '<p>JavaScript Error: ' + error.message + '</p>'
|
||||
+ "<p>This usually means there's a typo in your chart specification. "
|
||||
+ "See the javascript console for the full traceback.</p>"
|
||||
+ '</div>'
|
||||
);
|
||||
}
|
||||
|
||||
const reembed = async () => {
|
||||
if (finalize != null) {
|
||||
finalize();
|
||||
}
|
||||
|
||||
model.set("local_tz", Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||
|
||||
let spec = structuredClone(model.get("spec"));
|
||||
if (spec == null) {
|
||||
// Remove any existing chart and return
|
||||
while (el.firstChild) {
|
||||
el.removeChild(el.lastChild);
|
||||
}
|
||||
model.save_changes();
|
||||
return;
|
||||
}
|
||||
let embedOptions = structuredClone(model.get("embed_options")) ?? undefined;
|
||||
|
||||
let api;
|
||||
try {
|
||||
api = await vegaEmbed(el, spec, embedOptions);
|
||||
} catch (error) {
|
||||
showError(error)
|
||||
return;
|
||||
}
|
||||
|
||||
finalize = api.finalize;
|
||||
|
||||
// Debounce config
|
||||
const wait = model.get("debounce_wait") ?? 10;
|
||||
const debounceOpts = {leading: false, trailing: true};
|
||||
if (model.get("max_wait") ?? true) {
|
||||
debounceOpts["maxWait"] = wait;
|
||||
}
|
||||
|
||||
const initialSelections = {};
|
||||
for (const selectionName of Object.keys(model.get("_vl_selections"))) {
|
||||
const storeName = `${selectionName}_store`;
|
||||
const selectionHandler = (_, value) => {
|
||||
const newSelections = cleanJson(model.get("_vl_selections") ?? {});
|
||||
const store = cleanJson(api.view.data(storeName) ?? []);
|
||||
|
||||
newSelections[selectionName] = {value, store};
|
||||
model.set("_vl_selections", newSelections);
|
||||
model.save_changes();
|
||||
};
|
||||
api.view.addSignalListener(selectionName, lodashDebounce(selectionHandler, wait, debounceOpts));
|
||||
|
||||
initialSelections[selectionName] = {
|
||||
value: cleanJson(api.view.signal(selectionName) ?? {}),
|
||||
store: cleanJson(api.view.data(storeName) ?? [])
|
||||
}
|
||||
}
|
||||
model.set("_vl_selections", initialSelections);
|
||||
|
||||
const initialParams = {};
|
||||
for (const paramName of Object.keys(model.get("_params"))) {
|
||||
const paramHandler = (_, value) => {
|
||||
const newParams = JSON.parse(JSON.stringify(model.get("_params"))) || {};
|
||||
newParams[paramName] = value;
|
||||
model.set("_params", newParams);
|
||||
model.save_changes();
|
||||
};
|
||||
api.view.addSignalListener(paramName, lodashDebounce(paramHandler, wait, debounceOpts));
|
||||
|
||||
initialParams[paramName] = api.view.signal(paramName) ?? null
|
||||
}
|
||||
model.set("_params", initialParams);
|
||||
model.save_changes();
|
||||
|
||||
// Param change callback
|
||||
model.on('change:_params', async (new_params) => {
|
||||
for (const [param, value] of Object.entries(new_params.changed._params)) {
|
||||
api.view.signal(param, value);
|
||||
}
|
||||
await api.view.runAsync();
|
||||
});
|
||||
|
||||
// Add signal/data listeners
|
||||
for (const watch of model.get("_js_watch_plan") ?? []) {
|
||||
if (watch.namespace === "data") {
|
||||
const dataHandler = (_, value) => {
|
||||
model.set("_js_to_py_updates", [{
|
||||
namespace: "data",
|
||||
name: watch.name,
|
||||
scope: watch.scope,
|
||||
value: cleanJson(value)
|
||||
}]);
|
||||
model.save_changes();
|
||||
};
|
||||
addDataListener(api.view, watch.name, watch.scope, lodashDebounce(dataHandler, wait, debounceOpts))
|
||||
|
||||
} else if (watch.namespace === "signal") {
|
||||
const signalHandler = (_, value) => {
|
||||
model.set("_js_to_py_updates", [{
|
||||
namespace: "signal",
|
||||
name: watch.name,
|
||||
scope: watch.scope,
|
||||
value: cleanJson(value)
|
||||
}]);
|
||||
model.save_changes();
|
||||
};
|
||||
|
||||
addSignalListener(api.view, watch.name, watch.scope, lodashDebounce(signalHandler, wait, debounceOpts))
|
||||
}
|
||||
}
|
||||
|
||||
// Add signal/data updaters
|
||||
model.on('change:_py_to_js_updates', async (updates) => {
|
||||
for (const update of updates.changed._py_to_js_updates ?? []) {
|
||||
if (update.namespace === "signal") {
|
||||
setSignalValue(api.view, update.name, update.scope, update.value);
|
||||
} else if (update.namespace === "data") {
|
||||
setDataValue(api.view, update.name, update.scope, update.value);
|
||||
}
|
||||
}
|
||||
await api.view.runAsync();
|
||||
});
|
||||
}
|
||||
|
||||
model.on('change:spec', reembed);
|
||||
model.on('change:embed_options', reembed);
|
||||
model.on('change:debounce_wait', reembed);
|
||||
model.on('change:max_wait', reembed);
|
||||
await reembed();
|
||||
}
|
||||
|
||||
function cleanJson(data) {
|
||||
return JSON.parse(JSON.stringify(data))
|
||||
}
|
||||
|
||||
function getNestedRuntime(view, scope) {
|
||||
var runtime = view._runtime;
|
||||
for (const index of scope) {
|
||||
runtime = runtime.subcontext[index];
|
||||
}
|
||||
return runtime
|
||||
}
|
||||
|
||||
function lookupSignalOp(view, name, scope) {
|
||||
let parent_runtime = getNestedRuntime(view, scope);
|
||||
return parent_runtime.signals[name] ?? null;
|
||||
}
|
||||
|
||||
function dataRef(view, name, scope) {
|
||||
let parent_runtime = getNestedRuntime(view, scope);
|
||||
return parent_runtime.data[name];
|
||||
}
|
||||
|
||||
export function setSignalValue(view, name, scope, value) {
|
||||
let signal_op = lookupSignalOp(view, name, scope);
|
||||
view.update(signal_op, value);
|
||||
}
|
||||
|
||||
export function setDataValue(view, name, scope, value) {
|
||||
let dataset = dataRef(view, name, scope);
|
||||
let changeset = view.changeset().remove(() => true).insert(value)
|
||||
dataset.modified = true;
|
||||
view.pulse(dataset.input, changeset);
|
||||
}
|
||||
|
||||
export function addSignalListener(view, name, scope, handler) {
|
||||
let signal_op = lookupSignalOp(view, name, scope);
|
||||
return addOperatorListener(
|
||||
view,
|
||||
name,
|
||||
signal_op,
|
||||
handler,
|
||||
);
|
||||
}
|
||||
|
||||
export function addDataListener(view, name, scope, handler) {
|
||||
let dataset = dataRef(view, name, scope).values;
|
||||
return addOperatorListener(
|
||||
view,
|
||||
name,
|
||||
dataset,
|
||||
handler,
|
||||
);
|
||||
}
|
||||
|
||||
// Private helpers from Vega for dealing with nested signals/data
|
||||
function findOperatorHandler(op, handler) {
|
||||
const h = (op._targets || [])
|
||||
.filter(op => op._update && op._update.handler === handler);
|
||||
return h.length ? h[0] : null;
|
||||
}
|
||||
|
||||
function addOperatorListener(view, name, op, handler) {
|
||||
let h = findOperatorHandler(op, handler);
|
||||
if (!h) {
|
||||
h = trap(view, () => handler(name, op.value));
|
||||
h.handler = handler;
|
||||
view.on(op, null, h);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
function trap(view, fn) {
|
||||
return !fn ? null : function() {
|
||||
try {
|
||||
fn.apply(this, arguments);
|
||||
} catch (error) {
|
||||
view.error(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default { render }
|
||||
Reference in New Issue
Block a user