From 32844509bfcf823e963ecad628951babcaac9dd2 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 22 Oct 2021 15:19:15 +0200 Subject: [PATCH 01/20] possible bind values collection --- src/Configuration.jl | 1 + src/evaluation/Run.jl | 26 ++++++++++++++--- src/evaluation/WorkspaceManager.jl | 24 ++++++++++++++++ src/runner/PlutoRunner.jl | 45 ++++++++++++++++++++++++------ 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/Configuration.jl b/src/Configuration.jl index b2fb857f42..c200b65714 100644 --- a/src/Configuration.jl +++ b/src/Configuration.jl @@ -55,6 +55,7 @@ The HTTP server options. See [`SecurityOptions`](@ref) for additional settings. notebook::Union{Nothing,String, Vector{<: String}} = nothing init_with_file_viewer::Bool=false simulated_lag::Real=0.0 + collect_possible_bind_values::Bool=true end """ diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index b51d1856fe..1b31fcccba 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -6,12 +6,24 @@ import .WorkspaceManager: macroexpand_in_workspace Base.push!(x::Set{Cell}) = x "Run given cells and all the cells that depend on them, based on the topology information before and after the changes." -function run_reactive!(session::ServerSession, notebook::Notebook, old_topology::NotebookTopology, new_topology::NotebookTopology, roots::Vector{Cell}; deletion_hook::Function=WorkspaceManager.move_vars, persist_js_state::Bool=false, already_in_run::Bool=false, already_run::Vector{Cell}=Cell[])::TopologicalOrder - if !already_in_run && length(already_run) == 0 +function run_reactive!( + session::ServerSession, + notebook::Notebook, + old_topology::NotebookTopology, + new_topology::NotebookTopology, + roots::Vector{Cell}; + deletion_hook::Function=WorkspaceManager.move_vars, + persist_js_state::Bool=false, + already_in_run::Bool=false, + already_run::Vector{Cell}=Cell[], +)::TopologicalOrder + if !already_in_run && length(already_run) == 0 # make sure that we're the only `run_reactive!` being executed - like a semaphor take!(notebook.executetoken) - old_workspace_name, new_workspace_name = WorkspaceManager.bump_workspace_module((session, notebook)) + sn = (session, notebook) + session.options.server.collect_possible_bind_values && WorkspaceManager.enable_collecting_possible_bind_values(sn) + old_workspace_name, new_workspace_name = WorkspaceManager.bump_workspace_module(sn) if !is_resolved(new_topology) unresolved_topology = new_topology @@ -133,7 +145,7 @@ function run_reactive!(session::ServerSession, notebook::Notebook, old_topology: update_dependency_cache!(notebook) session.options.server.disable_writing_notebook_files || save_notebook(notebook) - return run_reactive!(session, notebook, new_topology, new_new_topology, to_run; deletion_hook=deletion_hook, persist_js_state=persist_js_state, already_in_run=true, already_run=to_run[1:i]) + return run_reactive!(session, notebook, new_topology, new_new_topology, to_run; deletion_hook=deletion_hook, persist_js_state=persist_js_state, already_in_run=true) elseif !isempty(implicit_usings) new_soft_definitions = WorkspaceManager.collect_soft_definitions((session, notebook), implicit_usings) notebook.topology = new_new_topology = with_new_soft_definitions(new_topology, cell, new_soft_definitions) @@ -153,6 +165,12 @@ function run_reactive!(session::ServerSession, notebook::Notebook, old_topology: return new_order end +"Returns the set of all possible values for the binded variable `n` as returned by the widget implementation using `PlutoRunner._get_possible_values(element)`" +function possible_bond_values(session::ServerSession, notebook::Notebook, n::Symbol) + all_possible_values = WorkspaceManager.get_possible_bind_values((session, notebook)) + all_possible_values[n] +end + run_reactive_async!(session::ServerSession, notebook::Notebook, to_run::Vector{Cell}; kwargs...) = run_reactive_async!(session, notebook, notebook.topology, notebook.topology, to_run; kwargs...) function run_reactive_async!(session::ServerSession, notebook::Notebook, old::NotebookTopology, new::NotebookTopology, to_run::Vector{Cell}; run_async::Bool=true, kwargs...)::Union{Task,TopologicalOrder} diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index ba8497fcff..db2fd30e99 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -133,6 +133,30 @@ function bump_workspace_module(session_notebook::SN) old_name, new_name end +function enable_collecting_possible_bind_values(session_notebook::SN) + workspace = get_workspace(session_notebook) + pid = workspace.pid + + Distributed.remotecall_eval(Main, [pid], quote + PlutoRunner.enable_collecting_possible_bind_values!() + Core.eval(PlutoRunner, :(macro bind(def, element) _bind_collect(def, element) end)) + end) +end + +function get_possible_bind_values(session_notebook::SN) + workspace = get_workspace(session_notebook) + pid = workspace.pid + + possible_values = Distributed.remotecall_eval(Main, pid, quote + PlutoRunner.sanitize_value(PlutoRunner.PossibleBindValues[]) + end) + + @assert possible_values !== nothing "Tried to collect possible bind values when collection of possible bind values was not enabled" + + possible_values +end + + function create_emptyworkspacemodule(pid::Integer)::Symbol Distributed.remotecall_eval(Main, pid, :(PlutoRunner.increment_current_module())) end diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index bccd1fb64c..21ab4d1769 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1449,15 +1449,44 @@ The first cell will show a slider as the cell's output, ranging from 0 until 100 The second cell will show the square of `x`, and is updated in real-time as the slider is moved. """ macro bind(def, element) - if def isa Symbol - quote - local el = $(esc(element)) + _bind(def, element) +end + +struct πŸ”– end + +"@bind widgets should implement a method to this function to return the set of possible values for a particular instance of a widget." +_get_possible_values(bind_instance) = πŸ”–() + +const PossibleBindValues = Ref{Union{Nothing,Dict{Symbol,Any}}}(nothing) + +function _set_possible_bind_values(def, bind_instance) + PossibleBindValues[] === nothing && throw("Tried to collect possible bind values without initializing the container") + PossibleBindValues[][def] = _get_possible_values(bind_instance) +end + +function enable_collecting_possible_bind_values!() + PossibleBindValues[] === nothing && return + PossibleBindValues[] = Dict{Symbol,Any}(); +end + +function _bind_collect(def, element) + ex = _bind(def, element) + + Expr(:block, ex.args[1:2], + Expr(:call, PlutoRunner._set_possible_bind_values, QuoteNode(def), ex.args[2].args[1]), + ex.args[3:end]...) +end + +function _bind(def, element) + if def isa Symbol + quote + local el = $(esc(element)) global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing - PlutoRunner.Bond(el, $(Meta.quot(def))) - end - else - :(throw(ArgumentError("""\nMacro example usage: \n\n\t@bind my_number html""\n\n"""))) - end + PlutoRunner.Bond(el, $(Meta.quot(def))) + end + else + :(throw(ArgumentError("""\nMacro example usage: \n\n\t@bind my_number html""\n\n"""))) + end end """ From d0476c6b4b468507509e52fb33078b9a1468a356 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 22 Oct 2021 15:27:49 +0200 Subject: [PATCH 02/20] oops --- src/runner/PlutoRunner.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 21ab4d1769..8bca02ce8f 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1465,7 +1465,7 @@ function _set_possible_bind_values(def, bind_instance) end function enable_collecting_possible_bind_values!() - PossibleBindValues[] === nothing && return + PossibleBindValues[] !== nothing && return PossibleBindValues[] = Dict{Symbol,Any}(); end From 4af278f4e77273990d62269da797c71c8c78476e Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 22 Oct 2021 15:29:21 +0200 Subject: [PATCH 03/20] oopsie --- src/evaluation/WorkspaceManager.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index db2fd30e99..f98b907f2e 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -148,7 +148,7 @@ function get_possible_bind_values(session_notebook::SN) pid = workspace.pid possible_values = Distributed.remotecall_eval(Main, pid, quote - PlutoRunner.sanitize_value(PlutoRunner.PossibleBindValues[]) + PlutoRunner.PossibleBindValues[] end) @assert possible_values !== nothing "Tried to collect possible bind values when collection of possible bind values was not enabled" From f42d6d4e14a7592c47174affb495aba3bf46f19b Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 22 Oct 2021 16:16:28 +0200 Subject: [PATCH 04/20] testy --- frontend/common/SliderServerClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/common/SliderServerClient.js b/frontend/common/SliderServerClient.js index f636d1ac38..b871c98a5f 100644 --- a/frontend/common/SliderServerClient.js +++ b/frontend/common/SliderServerClient.js @@ -14,7 +14,7 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, notebookfile_hash.then((x) => console.log("Notebook file hash:", x)) const bond_connections = notebookfile_hash - .then((hash) => fetch(trailingslash(launch_params.slider_server_url) + "bondconnections/" + encodeURIComponent(hash) + "/")) + .then((hash) => fetch(trailingslash(launch_params.slider_server_url) + "bondconnections/" + encodeURIComponent(hash) + "")) .then((r) => r.arrayBuffer()) .then((b) => unpack(new Uint8Array(b))) From 80408bd11a47d3b08fa0ede69f372f1f76a74674 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 22 Oct 2021 16:29:23 +0200 Subject: [PATCH 05/20] try to canonalize staterequest --- frontend/common/SliderServerClient.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/common/SliderServerClient.js b/frontend/common/SliderServerClient.js index b871c98a5f..7ce37052c9 100644 --- a/frontend/common/SliderServerClient.js +++ b/frontend/common/SliderServerClient.js @@ -35,7 +35,12 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, console.debug("Requesting bonds", bonds_to_set.current, to_send) bonds_to_set.current = new Set() - const mybonds_filtered = Object.fromEntries(Object.entries(mybonds).filter(([k, v]) => to_send.has(k))) + const mybonds_filtered = Object.fromEntries( + _.sortBy( + Object.entries(mybonds).filter(([k, v]) => to_send.has(k)), + ([k, v]) => k + ) + ) const packed = pack(mybonds_filtered) @@ -75,11 +80,11 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, set_bond: async (symbol, value, is_first_value) => { setStatePromise( immer((state) => { - state.notebook.bonds[symbol] = { value: value, is_first_value: is_first_value } + state.notebook.bonds[symbol] = { value: value, is_first_value: true } }) ) if (mybonds[symbol] == null || !_.isEqual(mybonds[symbol].value, value)) { - mybonds[symbol] = { value: _.cloneDeep(value), is_first_value: is_first_value } + mybonds[symbol] = { value: _.cloneDeep(value), is_first_value: true } bonds_to_set.current.add(symbol) await request_bond_response() } From b5af2df3ae326e5bad4bac5f4731851f037f4f3e Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Fri, 22 Oct 2021 18:07:47 +0200 Subject: [PATCH 06/20] Update Notebook.jl --- src/notebook/Notebook.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook/Notebook.jl b/src/notebook/Notebook.jl index 952bf5b94e..742b5f1a77 100644 --- a/src/notebook/Notebook.jl +++ b/src/notebook/Notebook.jl @@ -9,7 +9,7 @@ mutable struct BondValue # This is only so the client can send this, the updater will always put this to `false` is_first_value::Bool end -function Base.convert(::Type{BondValue}, dict::Dict) +function Base.convert(::Type{BondValue}, dict::AbstractDict) BondValue(dict["value"], something(get(dict, "is_first_value", false), false)) end From 09b066a77fd7607911a04942e9df6e683e78ac1e Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 25 Oct 2021 11:19:28 +0200 Subject: [PATCH 07/20] add err msg --- src/evaluation/Run.jl | 4 +++- src/runner/PlutoRunner.jl | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index 1b31fcccba..df06494d94 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -168,7 +168,9 @@ end "Returns the set of all possible values for the binded variable `n` as returned by the widget implementation using `PlutoRunner._get_possible_values(element)`" function possible_bond_values(session::ServerSession, notebook::Notebook, n::Symbol) all_possible_values = WorkspaceManager.get_possible_bind_values((session, notebook)) - all_possible_values[n] + bond_possible_values = all_possible_values[n] + @assert !(bond_possible_values isa PlutoRunner.πŸ”–) "The widget type for bind value $n has not specified its set of possible values" + bond_possible_values end run_reactive_async!(session::ServerSession, notebook::Notebook, to_run::Vector{Cell}; kwargs...) = run_reactive_async!(session, notebook, notebook.topology, notebook.topology, to_run; kwargs...) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 8bca02ce8f..03b1daad50 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1452,6 +1452,7 @@ macro bind(def, element) _bind(def, element) end +"Used to represent an undefined set of possible values" struct πŸ”– end "@bind widgets should implement a method to this function to return the set of possible values for a particular instance of a widget." From 8e494623e0313c1cfc0ccd4f2bbde5756090edc6 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 25 Oct 2021 14:41:34 +0200 Subject: [PATCH 08/20] expose new API for widget packages --- src/runner/PlutoRunner.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 03b1daad50..2e154cfa20 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1460,6 +1460,9 @@ _get_possible_values(bind_instance) = πŸ”–() const PossibleBindValues = Ref{Union{Nothing,Dict{Symbol,Any}}}(nothing) +"Whether or not the widget packages should define methods to `PlutoRunner._get_possible_values` at package init." +should_set_possible_bind_values() = PossibleBindValues[] !== nothing + function _set_possible_bind_values(def, bind_instance) PossibleBindValues[] === nothing && throw("Tried to collect possible bind values without initializing the container") PossibleBindValues[][def] = _get_possible_values(bind_instance) From cc550fd16aa2d03f52231a1fba216b3e3025ac0d Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 3 Nov 2021 23:02:01 +0100 Subject: [PATCH 09/20] update to use abstract pluto dingjetes --- src/evaluation/Run.jl | 27 +++------------------------ src/evaluation/RunBonds.jl | 3 +++ src/evaluation/WorkspaceManager.jl | 15 ++------------- src/runner/PlutoRunner.jl | 15 ++++++++++++++- 4 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index 2cd726c83b..53403ec7fd 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -5,25 +5,12 @@ import .WorkspaceManager: macroexpand_in_workspace Base.push!(x::Set{Cell}) = x -"Run given cells and all the cells that depend on them, based on the topology information before and after the changes." -function run_reactive!( - session::ServerSession, - notebook::Notebook, - old_topology::NotebookTopology, - new_topology::NotebookTopology, - roots::Vector{Cell}; - deletion_hook::Function=WorkspaceManager.move_vars, - persist_js_state::Bool=false, - already_in_run::Bool=false, - already_run::Vector{Cell}=Cell[], -)::TopologicalOrder - if !already_in_run && length(already_run) == 0 +function run_reactive!(session::ServerSession, notebook::Notebook, old_topology::NotebookTopology, new_topology::NotebookTopology, roots::Vector{Cell}; deletion_hook::Function=WorkspaceManager.move_vars, persist_js_state::Bool=false, already_in_run::Bool=false, already_run::Vector{Cell}=Cell[])::TopologicalOrder + if !already_in_run && length(already_run) == 0 # make sure that we're the only `run_reactive!` being executed - like a semaphor take!(notebook.executetoken) - sn = (session, notebook) - session.options.server.collect_possible_bind_values && WorkspaceManager.enable_collecting_possible_bind_values(sn) - old_workspace_name, new_workspace_name = WorkspaceManager.bump_workspace_module(sn) + old_workspace_name, new_workspace_name = WorkspaceManager.bump_workspace_module((session, notebook)) if !is_resolved(new_topology) unresolved_topology = new_topology @@ -165,14 +152,6 @@ function run_reactive!( return new_order end -"Returns the set of all possible values for the binded variable `n` as returned by the widget implementation using `PlutoRunner._get_possible_values(element)`" -function possible_bond_values(session::ServerSession, notebook::Notebook, n::Symbol) - all_possible_values = WorkspaceManager.get_possible_bind_values((session, notebook)) - bond_possible_values = all_possible_values[n] - @assert !(bond_possible_values isa PlutoRunner.πŸ”–) "The widget type for bind value $n has not specified its set of possible values" - bond_possible_values -end - run_reactive_async!(session::ServerSession, notebook::Notebook, to_run::Vector{Cell}; kwargs...) = run_reactive_async!(session, notebook, notebook.topology, notebook.topology, to_run; kwargs...) function run_reactive_async!(session::ServerSession, notebook::Notebook, old::NotebookTopology, new::NotebookTopology, to_run::Vector{Cell}; run_async::Bool=true, kwargs...)::Union{Task,TopologicalOrder} diff --git a/src/evaluation/RunBonds.jl b/src/evaluation/RunBonds.jl index a202125b1f..4852c1da0a 100644 --- a/src/evaluation/RunBonds.jl +++ b/src/evaluation/RunBonds.jl @@ -45,3 +45,6 @@ function set_bond_values_reactive(; session::ServerSession, notebook::Notebook, run_reactive_async!(session, notebook, to_reeval; deletion_hook=custom_deletion_hook, persist_js_state=true, run_async=false, kwargs...) end + +"Returns the set of all possible values for the binded variable `n` as returned by the widget implementation using `AbstractPlutoDingetjes.possible_bond_values(element)`" +possible_bond_values(session::ServerSession, notebook::Notebook, n::Symbol) = WorkspaceManager.possible_bond_values((session,notebook), n) \ No newline at end of file diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index f98b907f2e..201409772e 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -133,22 +133,12 @@ function bump_workspace_module(session_notebook::SN) old_name, new_name end -function enable_collecting_possible_bind_values(session_notebook::SN) - workspace = get_workspace(session_notebook) - pid = workspace.pid - - Distributed.remotecall_eval(Main, [pid], quote - PlutoRunner.enable_collecting_possible_bind_values!() - Core.eval(PlutoRunner, :(macro bind(def, element) _bind_collect(def, element) end)) - end) -end - -function get_possible_bind_values(session_notebook::SN) +function possible_bond_values(session_notebook::SN, n::Symbol) workspace = get_workspace(session_notebook) pid = workspace.pid possible_values = Distributed.remotecall_eval(Main, pid, quote - PlutoRunner.PossibleBindValues[] + PlutoRunner.possible_bond_values($(QuoteNode(n))) end) @assert possible_values !== nothing "Tried to collect possible bind values when collection of possible bind values was not enabled" @@ -156,7 +146,6 @@ function get_possible_bind_values(session_notebook::SN) possible_values end - function create_emptyworkspacemodule(pid::Integer)::Symbol Distributed.remotecall_eval(Main, pid, :(PlutoRunner.increment_current_module())) end diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 613018ddb9..9ac09183ef 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1133,12 +1133,14 @@ const integrations = Integration[ @assert v"1.0.0" <= AbstractPlutoDingetjes.MY_VERSION < v"2.0.0" initial_value_getter_ref[] = AbstractPlutoDingetjes.Bonds.initial_value transform_value_ref[] = AbstractPlutoDingetjes.Bonds.transform_value - + possible_bond_values_ref[] = AbstractPlutoDingetjes.Bonds.possible_values + push!(supported_integration_features, AbstractPlutoDingetjes, AbstractPlutoDingetjes.Bonds, AbstractPlutoDingetjes.Bonds.initial_value, AbstractPlutoDingetjes.Bonds.transform_value, + AbstractPlutoDingetjes.Bonds.possible_values, ) end, ), @@ -1446,6 +1448,16 @@ function transform_bond_value(s::Symbol, value_from_js) end end +function possible_bond_values(s::Symbol) + element = get(registered_bond_elements, s, nothing) + return try + possible_bond_values_ref[](element) + catch e + @error "Could not collect possible bond values for $s" exception=(e, catch_backtrace()) + rethrow(e) + end +end + """ _β€œThe name is Bond, James Bond.”_ @@ -1488,6 +1500,7 @@ end const initial_value_getter_ref = Ref{Function}(element -> missing) const transform_value_ref = Ref{Function}((element, x) -> x) +const possible_bond_values_ref = Ref{Function}(_ -> throw("AbstractPlutoDingetjes is not loaded, could not collect possible bind values")) """ `@bind symbol element` From b96eae7aa888847b97b498cd1b9193439cee6319 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 3 Nov 2021 23:05:39 +0100 Subject: [PATCH 10/20] rm --- src/Configuration.jl | 1 - src/evaluation/Run.jl | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Configuration.jl b/src/Configuration.jl index 64b6657b6e..80fa87639a 100644 --- a/src/Configuration.jl +++ b/src/Configuration.jl @@ -55,7 +55,6 @@ The HTTP server options. See [`SecurityOptions`](@ref) for additional settings. notebook::Union{Nothing,String, Vector{<: String}} = nothing init_with_file_viewer::Bool=false simulated_lag::Real=0.0 - collect_possible_bind_values::Bool=true end """ diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index 53403ec7fd..0b690bc1e9 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -5,6 +5,7 @@ import .WorkspaceManager: macroexpand_in_workspace Base.push!(x::Set{Cell}) = x + "Run given cells and all the cells that depend on them, based on the topology information before and after the changes." function run_reactive!(session::ServerSession, notebook::Notebook, old_topology::NotebookTopology, new_topology::NotebookTopology, roots::Vector{Cell}; deletion_hook::Function=WorkspaceManager.move_vars, persist_js_state::Bool=false, already_in_run::Bool=false, already_run::Vector{Cell}=Cell[])::TopologicalOrder if !already_in_run && length(already_run) == 0 # make sure that we're the only `run_reactive!` being executed - like a semaphor @@ -132,7 +133,7 @@ function run_reactive!(session::ServerSession, notebook::Notebook, old_topology: update_dependency_cache!(notebook) session.options.server.disable_writing_notebook_files || save_notebook(notebook) - return run_reactive!(session, notebook, new_topology, new_new_topology, to_run; deletion_hook=deletion_hook, persist_js_state=persist_js_state, already_in_run=true) + return run_reactive!(session, notebook, new_topology, new_new_topology, to_run; deletion_hook=deletion_hook, persist_js_state=persist_js_state, already_in_run=true, already_run=to_run[1:i]) elseif !isempty(implicit_usings) new_soft_definitions = WorkspaceManager.collect_soft_definitions((session, notebook), implicit_usings) notebook.topology = new_new_topology = with_new_soft_definitions(new_topology, cell, new_soft_definitions) From a1d8ab916ba1a39ed4af2859bfce58e8d1dac3c6 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 3 Nov 2021 23:18:08 +0100 Subject: [PATCH 11/20] test --- src/runner/PlutoRunner.jl | 2 +- test/Bonds.jl | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 9ac09183ef..edc22cfdd9 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1454,7 +1454,7 @@ function possible_bond_values(s::Symbol) possible_bond_values_ref[](element) catch e @error "Could not collect possible bond values for $s" exception=(e, catch_backtrace()) - rethrow(e) + rethrow("Could not collect possible bond values for $s, err = $(string(e))") end end diff --git a/test/Bonds.jl b/test/Bonds.jl index 447f32e782..446ead2927 100644 --- a/test/Bonds.jl +++ b/test/Bonds.jl @@ -90,6 +90,8 @@ import Pluto: update_run!, WorkspaceManager, ClientSession, ServerSession, Noteb Base.show(io::IO, m::MIME"text/html", os::NewSlider) = write(io, "") Bonds.initial_value(os::NewSlider) = 1 + + Bonds.possible_values(s::NewSlider) = [1,2,3] end """), Cell(""" @@ -172,9 +174,8 @@ import Pluto: update_run!, WorkspaceManager, ClientSession, ServerSession, Noteb @test notebook.cells[7].output.body == "false" @test notebook.cells[8].output.body == "false" - - - + @test Pluto.possible_bond_values(🍭, notebook, :x_new) == [1,2,3] + @test noerror(notebook.cells[9]) @test noerror(notebook.cells[10]) @test noerror(notebook.cells[11]) From 25ea69c8e68b10876339add9b976232372b2e31a Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 15 Nov 2021 22:59:44 +0100 Subject: [PATCH 12/20] tweak --- src/runner/PlutoRunner.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index be6875b8a3..b8a03a29a7 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1664,7 +1664,7 @@ end const initial_value_getter_ref = Ref{Function}(element -> missing) const transform_value_ref = Ref{Function}((element, x) -> x) -const possible_bond_values_ref = Ref{Function}(_ -> throw("AbstractPlutoDingetjes is not loaded, could not collect possible bind values")) +const possible_bond_values_ref = Ref{Function}((_args...; _kwargs...) -> throw("AbstractPlutoDingetjes is not loaded, could not collect possible bind values")) """ `@bind symbol element` From 924a4bdbb15df7ebbca4b2dc91145bf6812b712b Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 26 Nov 2021 21:01:27 +0100 Subject: [PATCH 13/20] handle NotGiven and InfinitePossibilities --- src/runner/PlutoRunner.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index b8a03a29a7..946ef59132 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1614,12 +1614,15 @@ end function possible_bond_values(s::Symbol) element = get(registered_bond_elements, s, nothing) - return try - possible_bond_values_ref[](element) - catch e - @error "Could not collect possible bond values for $s" exception=(e, catch_backtrace()) - rethrow("Could not collect possible bond values for $s, err = $(string(e))") + possible_values = possible_bond_values_ref[](element) + + if possible_values isa AbstractPlutoDingetjes.Bonds.InfinitePossibilities + error("Bond \"$s\" has an unlimited number of possible values, try changing the `@bind` to something with a finite number of possible values like `PlutoUI.CheckBox(...)` or `PlutoUI.Slider(...)` instead.") + elseif possible_values isa AbstractPlutoDingetjes.Bonds.NotGiven + error("Bond \"$s\" did not specify its possible values with `AbstractPlutoDingetjes.Bond.possible_values()`. Try using PlutoUI for the `@bind` values.") end + + possible_values end """ From 978e5650b4ad2d2a2b49cf8dbc5d6b04db46d87d Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 29 Nov 2021 19:59:24 +0100 Subject: [PATCH 14/20] Restore RunBonds.jl --- src/evaluation/RunBonds.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/evaluation/RunBonds.jl b/src/evaluation/RunBonds.jl index a873a74a39..783a16b43c 100644 --- a/src/evaluation/RunBonds.jl +++ b/src/evaluation/RunBonds.jl @@ -45,6 +45,3 @@ function set_bond_values_reactive(; session::ServerSession, notebook::Notebook, run_reactive_async!(session, notebook, to_reeval; deletion_hook=custom_deletion_hook, user_requested_run=false, run_async=false, kwargs...) end - -"Returns the set of all possible values for the binded variable `n` as returned by the widget implementation using `AbstractPlutoDingetjes.possible_bond_values(element)`" -possible_bond_values(session::ServerSession, notebook::Notebook, n::Symbol) = WorkspaceManager.possible_bond_values((session,notebook), n) \ No newline at end of file From 97867bb0e5f45e235da902da9905f663dad81181 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 29 Nov 2021 19:59:32 +0100 Subject: [PATCH 15/20] Restore WorkspaceManager.jl --- src/evaluation/WorkspaceManager.jl | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index 23fd790ca8..b09dd7ee17 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -154,19 +154,6 @@ function bump_workspace_module(session_notebook::SN) old_name, new_name end -function possible_bond_values(session_notebook::SN, n::Symbol) - workspace = get_workspace(session_notebook) - pid = workspace.pid - - possible_values = Distributed.remotecall_eval(Main, pid, quote - PlutoRunner.possible_bond_values($(QuoteNode(n))) - end) - - @assert possible_values !== nothing "Tried to collect possible bind values when collection of possible bind values was not enabled" - - possible_values -end - function create_emptyworkspacemodule(pid::Integer)::Symbol Distributed.remotecall_eval(Main, pid, :(PlutoRunner.increment_current_module())) end From 96f4106204f3747bbada9b907174cd98ce892c7d Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 29 Nov 2021 19:59:42 +0100 Subject: [PATCH 16/20] Restore Notebook.jl --- src/notebook/Notebook.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notebook/Notebook.jl b/src/notebook/Notebook.jl index 41e724c163..af4d7a3a60 100644 --- a/src/notebook/Notebook.jl +++ b/src/notebook/Notebook.jl @@ -9,7 +9,7 @@ mutable struct BondValue # This is only so the client can send this, the updater will always put this to `false` is_first_value::Bool end -function Base.convert(::Type{BondValue}, dict::AbstractDict) +function Base.convert(::Type{BondValue}, dict::Dict) BondValue(dict["value"], something(get(dict, "is_first_value", false), false)) end @@ -358,4 +358,4 @@ function sample_notebook(name::String) nb = load_notebook_nobackup(file) nb.path = tempname() * ".jl" nb -end \ No newline at end of file +end From fa603216d3b03e4d4cda0a740f30d3e79253b870 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 29 Nov 2021 19:59:47 +0100 Subject: [PATCH 17/20] Restore PlutoRunner.jl --- src/runner/PlutoRunner.jl | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index c5adac4ef6..c17543401c 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -1301,14 +1301,12 @@ const integrations = Integration[ @assert v"1.0.0" <= AbstractPlutoDingetjes.MY_VERSION < v"2.0.0" initial_value_getter_ref[] = AbstractPlutoDingetjes.Bonds.initial_value transform_value_ref[] = AbstractPlutoDingetjes.Bonds.transform_value - possible_bond_values_ref[] = AbstractPlutoDingetjes.Bonds.possible_values - + push!(supported_integration_features, AbstractPlutoDingetjes, AbstractPlutoDingetjes.Bonds, AbstractPlutoDingetjes.Bonds.initial_value, AbstractPlutoDingetjes.Bonds.transform_value, - AbstractPlutoDingetjes.Bonds.possible_values, ) end, ), @@ -1616,19 +1614,6 @@ function transform_bond_value(s::Symbol, value_from_js) end end -function possible_bond_values(s::Symbol) - element = get(registered_bond_elements, s, nothing) - possible_values = possible_bond_values_ref[](element) - - if possible_values isa AbstractPlutoDingetjes.Bonds.InfinitePossibilities - error("Bond \"$s\" has an unlimited number of possible values, try changing the `@bind` to something with a finite number of possible values like `PlutoUI.CheckBox(...)` or `PlutoUI.Slider(...)` instead.") - elseif possible_values isa AbstractPlutoDingetjes.Bonds.NotGiven - error("Bond \"$s\" did not specify its possible values with `AbstractPlutoDingetjes.Bond.possible_values()`. Try using PlutoUI for the `@bind` values.") - end - - possible_values -end - """ _β€œThe name is Bond, James Bond.”_ @@ -1671,7 +1656,6 @@ end const initial_value_getter_ref = Ref{Function}(element -> missing) const transform_value_ref = Ref{Function}((element, x) -> x) -const possible_bond_values_ref = Ref{Function}((_args...; _kwargs...) -> throw("AbstractPlutoDingetjes is not loaded, could not collect possible bind values")) """ `@bind symbol element` From 1814abf36ef9fce266f2ac3e572c8cff479d683f Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 29 Nov 2021 19:59:52 +0100 Subject: [PATCH 18/20] Restore Bonds.jl --- test/Bonds.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/Bonds.jl b/test/Bonds.jl index 446ead2927..447f32e782 100644 --- a/test/Bonds.jl +++ b/test/Bonds.jl @@ -90,8 +90,6 @@ import Pluto: update_run!, WorkspaceManager, ClientSession, ServerSession, Noteb Base.show(io::IO, m::MIME"text/html", os::NewSlider) = write(io, "") Bonds.initial_value(os::NewSlider) = 1 - - Bonds.possible_values(s::NewSlider) = [1,2,3] end """), Cell(""" @@ -174,8 +172,9 @@ import Pluto: update_run!, WorkspaceManager, ClientSession, ServerSession, Noteb @test notebook.cells[7].output.body == "false" @test notebook.cells[8].output.body == "false" - @test Pluto.possible_bond_values(🍭, notebook, :x_new) == [1,2,3] - + + + @test noerror(notebook.cells[9]) @test noerror(notebook.cells[10]) @test noerror(notebook.cells[11]) From 663b0e14454ce5ce95ecda0a5033ae728f0c1b70 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 6 Dec 2021 17:15:33 +0100 Subject: [PATCH 19/20] Restore Notebook.jl From 8b06b5791cc80d9c8cb7773b4933e7fb7c2c8ffe Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 6 Dec 2021 20:23:19 +0100 Subject: [PATCH 20/20] Update SliderServerClient.js --- frontend/common/SliderServerClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/common/SliderServerClient.js b/frontend/common/SliderServerClient.js index c8f4d9f136..9e84241376 100644 --- a/frontend/common/SliderServerClient.js +++ b/frontend/common/SliderServerClient.js @@ -14,7 +14,7 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, notebookfile_hash.then((x) => console.log("Notebook file hash:", x)) const bond_connections = notebookfile_hash - .then((hash) => fetch(trailingslash(launch_params.slider_server_url) + "bondconnections/" + encodeURIComponent(hash) + "")) + .then((hash) => fetch(trailingslash(launch_params.slider_server_url) + "bondconnections/" + encodeURIComponent(hash))) .then((r) => r.arrayBuffer()) .then((b) => unpack(new Uint8Array(b)))