JuliaGizmos / WebIO.jl

A bridge between Julia and the Web.
https://juliagizmos.github.io/WebIO.jl/latest/
Other
228 stars 64 forks source link

julia knockout Invalid dependency (must be a url, file, or AssetRegistry path) #405

Open ClaudMor opened 4 years ago

ClaudMor commented 4 years ago

I still have the problem which was first presented in this issue and then moved to WebIO. I hope this is right place to ask.

The bug

using Interact

@manipulate for n in 1:1000
end
Invalid dependency (must be a url, file, or AssetRegistry path): \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Knockout\IP1uR\src\..\assets\knockout.js

Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] path2url(::SubString{String}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:209
 [3] dep2url(::String) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:226
 [4] lower(::Asset) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:51
 [5] lowerassets(::Asset) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:118
 [6] iterate at .\generator.jl:47 [inlined]
 [7] _collect(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(WebIO.lowerassets)}, ::Base.EltypeUnknown, ::Base.HasShape{1}) at .\array.jl:678
 [8] collect_similar(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(WebIO.lowerassets)}) at .\array.jl:607
 [9] map(::Function, ::Array{Any,1}) at .\abstractarray.jl:2072
 [10] lowerassets(::Async) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:119
 [11] (::WebIO.var"#23#24"{Async})(::Base.GenericIOBuffer{Array{UInt8,1}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\syntax.jl:221
 [12] sprint(::Function; context::Nothing, sizehint::Int64) at .\strings\io.jl:105
 [13] sprint at .\strings\io.jl:101 [inlined]
 [14] tojs at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\asset.jl:112 [inlined]
 [15] (::WebIO.var"#42#43"{Scope,WebIO.JSString})(::Base.GenericIOBuffer{Array{UInt8,1}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\syntax.jl:221
 [16] sprint(::Function; context::Nothing, sizehint::Int64) at .\strings\io.jl:105
 [17] sprint at .\strings\io.jl:101 [inlined]
 [18] onimport at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\WebIO\cOHMI\src\scope.jl:313 [inlined]
 [19] knockout(::Node{WebIO.DOM}, ::Array{Pair{String,Any},1}, ::WebIO.JSString; computed::Array{Pair{String,WebIO.JSString},1}, methods::Array{Any,1}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Knockout\IP1uR\src\Knockout.jl:124
 [20] input(::Interact.Bulma, ::Int64; extra_js::WebIO.JSString, extra_obs::Array{Pair{String,Array{String,1}},1}, label::Nothing, typ::String, wdgtyp::String, className::String, style::Dict{Any,Any}, isnumeric::Bool, computed::Array{Pair{String,WebIO.JSString},1}, attributes::Dict{Any,Any}, bind::String, bindto::String, valueUpdate::String, changes::Int64, kwargs::Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:min, :max, :step),Tuple{Int64,Int64,Int64}}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\InteractBase\NMcus\src\input.jl:259
 [21] input(::Int64; kwargs::Base.Iterators.Pairs{Symbol,Any,NTuple{9,Symbol},NamedTuple{(:bindto, :attributes, :extra_obs, :computed, :typ, :min, :max, :step, :className),Tuple{String,Dict{Any,Any},Array{Pair{String,Array{String,1}},1},Array{Pair{String,WebIO.JSString},1},String,Int64,Int64,Int64,String}}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Widgets\451tD\src\defaults.jl:10
 [22] slider(::Interact.Bulma, ::UnitRange{Int64}, ::Array{String,1}; className::String, readout::Bool, label::String, value::Int64, orientation::String, attributes::Dict{Any,Any}, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\InteractBase\NMcus\src\slider.jl:58
 [23] slider(::UnitRange{Int64}; kwargs::Base.Iterators.Pairs{Symbol,String,Tuple{Symbol},NamedTuple{(:label,),Tuple{String}}}) at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Widgets\451tD\src\defaults.jl:10
 [24] #widget#104 at \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Widgets\451tD\src\defaults.jl:56 [inlined]
 [25] top-level scope at\userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Widgets\451tD\src\manipulate.jl:91
 [26] top-level scope at In[6]:1

Context

julia> versioninfo()
Julia Version 1.4.1
Commit 381693d3df* (2020-04-14 17:20 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i7-2700K CPU @ 3.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, sandybridge)
Environment:
  JULIA_DEPOT_PATH = \userpath\.juliapro\JuliaPro_v1.4.1-1;Q:\juliapro\juliapro\Julia-1.4.1\local\share\julia;Q:\juliapro\juliapro\Julia-1.4.1\share\julia
  JULIA_EDITOR = "Q:\juliapro\juliapro\app-1.45.0\atom.exe"  -a
  JULIA_NUM_THREADS = 4
  JULIA_PKG_SERVER = pkg.juliacomputing.com
(@v1.4) pkg> st
Status `\userpath\.juliapro\JuliaPro_v1.4.1-1\environments\v1.4\Project.toml`
  [c52e3926] Atom v0.12.10 ⚲
  [7073ff75] IJulia v1.21.1
  [c601a237] Interact v0.10.3
  [e5e0dc1b] Juno v0.8.1 ⚲
  [4722fa14] PkgAuthentication v0.1.2
  [44d3d7a6] Weave v0.9.4
  [0f1e0344] WebIO v0.8.92
  [44cfe95a] Pkg
(@v1.4) pkg> st --manifest
Status `\userpath\.juliapro\JuliaPro_v1.4.1-1\environments\v1.4\Manifest.toml`
  [1520ce14] AbstractTrees v0.3.2
  [bf4720bc] AssetRegistry v0.1.0
  [c52e3926] Atom v0.12.10 ⚲
  [b99e7846] BinaryProvider v0.5.91
  [70588ee8] CSSUtil v0.1.0
  [00ebfdb7] CSTParser v2.2.0
  [7057c7e9] Cassette v0.3.1
  [53a63b46] CodeTools v0.7.0
  [da1fd8a2] CodeTracking v0.5.8
  [3da002f7] ColorTypes v0.9.1
  [5ae59095] Colors v0.11.2
  [34da2185] Compat v2.2.0
  [8f4d0f93] Conda v1.4.1
  [9a962f9c] DataAPI v1.1.0
  [864edb3b] DataStructures v0.17.11
  [e2d170a0] DataValueInterfaces v1.0.0
  [b4f34e82] Distances v0.8.2
  [33d173f1] DocSeeker v0.4.1
  [ffbed154] DocStringExtensions v0.8.1
  [5789e2e9] FileIO v1.2.4
  [53c48c17] FixedPointNumbers v0.7.1
  [08572546] FlameGraphs v0.2.0
  [de31a74c] FunctionalCollections v0.5.0
  [cd3eb016] HTTP v0.8.13
  [9fb69e20] Hiccup v0.2.2
  [eafb193a] Highlights v0.4.5
  [7073ff75] IJulia v1.21.1
  [9b13fd28] IndirectArrays v0.5.1
  [83e8ac13] IniFile v0.5.0
  [c601a237] Interact v0.10.3
  [d3863d7c] InteractBase v0.10.4
  [82899510] IteratorInterfaceExtensions v1.0.0
  [97c1335a] JSExpr v0.5.2
  [682c06a0] JSON v0.21.0
  [98e50ef6] JuliaFormatter v0.3.9
  [aa1ae85d] JuliaInterpreter v0.7.13
  [e5e0dc1b] Juno v0.8.1 ⚲
  [bcebb21b] Knockout v0.2.4
  [7c4cb9fa] LNR v0.2.1
  [50d2b5c4] Lazy v0.15.0
  [1d6d02ad] LeftChildRightSiblingTrees v0.1.2
  [1914dd2f] MacroTools v0.5.5
  [739be429] MbedTLS v0.7.0
  [442fdcdd] Measures v0.3.1
  [e89f7d12] Media v0.5.0
  [ffc61752] Mustache v1.0.2
  [510215fc] Observables v0.3.1
  [bac558e1] OrderedCollections v1.1.0
  [69de0a69] Parsers v1.0.1
  [fa939f87] Pidfile v1.1.0
  [4722fa14] PkgAuthentication v0.1.2
  [189a3867] Reexport v0.2.0
  [ae029012] Requires v1.0.1
  [b85f4697] SoftGlobalScope v1.0.10
  [88034a9c] StringDistances v0.6.3
  [3783bdb8] TableTraits v1.0.0
  [bd369af6] Tables v1.0.3
  [0796e94c] Tokenize v0.5.8
  [37b6cedf] Traceur v0.3.0
  [a2a6695c] TreeViews v0.3.0
  [30578b45] URIParser v0.4.0
  [81def892] VersionParsing v1.2.0
  [44d3d7a6] Weave v0.9.4
  [0f1e0344] WebIO v0.8.92
  [104b5d7c] WebSockets v1.5.2
  [cc8bc4a8] Widgets v0.6.2
  [ddb6d928] YAML v0.4.0
  [c2297ded] ZMQ v1.2.0
  [8f1865be] ZeroMQ_jll v4.3.2+1
  [2a0f44e3] Base64
  [ade2ca70] Dates
  [8bb1440f] DelimitedFiles
  [8ba89e20] Distributed
  [7b1f6079] FileWatching
  [b77e0a4c] InteractiveUtils
  [76f85450] LibGit2
  [8f399da3] Libdl
  [37e2e46d] LinearAlgebra
  [56ddb016] Logging
  [d6f4376e] Markdown
  [a63ad114] Mmap
  [44cfe95a] Pkg
  [de0858da] Printf
  [9abbd945] Profile
  [3fa0cd96] REPL
  [9a3f8284] Random
  [ea8e919c] SHA
  [9e88b42a] Serialization
  [1a1011a3] SharedArrays
  [6462fe0b] Sockets
  [2f01184e] SparseArrays
  [10745b16] Statistics
  [8dfed614] Test
  [cf7118a7] UUIDs
  [4ec0a83e] Unicode
julia> Pkg.status("WebIO")
Status `\usepath\.juliapro\JuliaPro_v1.4.1-1\environments\v1.4\Project.toml`
  [0f1e0344] WebIO v0.8.92

EDIT: the issue exists (with the same error) both on Juno and on jupyter lab.

(base) \userpath>jupyter labextension list
JupyterLab v1.2.6
No installed extensions

EDIT2: I looked in \userpath\.juliapro\JuliaPro_v1.4.1-1\packages\Knockout\IP1uR\src\ and there seems to be no ..\assets\knockout.js . There only is a Knockout.jl wich looks like this:

module Knockout

using WebIO, Observables, JSExpr, JSON
import Observables: off, observe, AbstractObservable, ObservablePair

export knockout

const knockout_js = joinpath(@__DIR__, "..", "assets", "knockout.js")
const knockout_punches_js = joinpath(@__DIR__, "..", "assets", "knockout_punches.js")

"""
`knockout(template, data=Dict(), extra_js = js""; computed = [], methods = [])`

Create a Knockout scope, with HTML structure provided by `template` and filled with `data`.
# Arguments
- `template` the `Node` that acts as the template. See [Knockout syntax](http://knockoutjs.com/documentation/value-binding.html)
- `data` is either a dictionary or an array of `propertyName => value` pairs.
If a property's value is an observable, this function automatically sets up Julia -> JS communication.
To set up JS to Julia communication set up an event handler on `scope[propertyName]` (by calling `on(f, scope[propertyName])`)
_before_ rendering the scope.
You can specify that you want some knockout observable to be computed as a function of other observables,
e.g `knockout(...; computed = Dict(:fullName => @js function(){this.firstName() + ' ' + this.lastName()}))`.
You can pass functions that you want available in the Knockout scope as keyword arguments to
`knockout` E.g. `knockout(...; methods=Dict(:sayhello=>@js function(){ alert("hello!") }))`
"""
function knockout(template, data=Dict(), extra_js = js""; computed = [], methods = [])
    widget = Scope(imports=[
        "knockout" => knockout_js,
        "knockout_punches" => knockout_punches_js,
    ])
    widget(template)
    ko_data = Dict()
    watches = Dict()
    for (k, v) in data
        skey = string(k)
        (v isa ObservablePair) && (v = v.second)
        if isa(v, AbstractObservable)
            # associate the observable with the widget
            setobservable!(widget, skey, v)

            # forward updates from Julia to Knockoutjs
            onjs(v, @js function (val)
                if val != this.model[$skey]()
                    this.valueFromJulia[$skey] = true
                    this.model[$skey](val)
                end
            end)

            # forward updates from Knockoutjs to Julia
            watches[skey] = @js this[$skey].subscribe( function(val)
                if !this.valueFromJulia[$skey]
                    $v[] = val
                end
                this.valueFromJulia[$skey] = false
            end, self)
            ko_data[skey] = @js $v[]
        else
            ko_data[skey] = v
        end
    end

    methods_dict = Dict()
    for (k, f) in methods
        skey = string(k)
        methods_dict[skey] = @js this[$skey] = $f
    end

    computed_dict = Dict()
    for (k, f) in computed
        skey = string(k)
        computed_dict[skey] = @js this[$skey] = ko.computed($f, this)
    end

    on_import = js"""
    function (ko, koPunches) {
        ko.punches.enableAll();
        ko.bindingHandlers.numericValue = {
            init: function(element, valueAccessor, allBindings, data, context) {
                var stringified = ko.observable(ko.unwrap(valueAccessor()));
                stringified.subscribe(function(value) {
                    var val = parseFloat(value);
                    if (!isNaN(val)) {
                        valueAccessor()(val);
                    }
                });
                valueAccessor().subscribe(function(value) {
                    var str = JSON.stringify(value);
                    if ((str == "0") && (["-0", "-0."].indexOf(stringified()) >= 0))
                         return;
                     if (["null", ""].indexOf(str) >= 0)
                         return;
                    stringified(str);
                });
                ko.applyBindingsToNode(
                    element,
                    {
                        value: stringified,
                        valueUpdate: allBindings.get('valueUpdate'),
                    },
                    context,
                );
            }
        };
        var json_data = $ko_data;
        var self = this;
        function AppViewModel() {
            for (var key in json_data) {
                var el = json_data[key];
                this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);
            }
            $(dict2js(methods_dict))
            $(dict2js(computed_dict))
            $(dict2js(watches))
            $extra_js
        }
        self.model = new AppViewModel();
        self.valueFromJulia = {};
        for (var key in json_data) {
            self.valueFromJulia[key] = false;
        }
        ko.applyBindings(self.model, self.dom);
    }
    """
    onimport(widget, on_import)
    widget
end

function dict2js(d::AbstractDict)
    isempty(d) ? js"" : js"$(values(d)...,)"
end

isnumeric(x) = false
isnumeric(x::Number) = true
isnumeric(x::Bool) = false
isnumeric(x::AbstractObservable) = isnumeric(x[])

js_lambda(s::String) = "function (){$s}"

end # module

Thanks for your help

duncanam commented 4 years ago

I'd like to +1 this- it occurs when I'm trying to use any Interact widget, across both Blink and Mux.

gabrevaya commented 4 years ago

Is there any solution for this already? I also find this issue when I try to use any Interact widget both in Juno-Atom and IJulia notebook.

twavv commented 4 years ago

It's possible that Knockout.jl failed to build (Knockout downloads the JS files at build time) and thus the asset that it's trying to register doesn't exist.

Try running

using Julia
Pkg.build("Knockout")
gabrevaya commented 4 years ago

Thanks a lot! I could solve the problem! Trying to build Knockout gave me a different error that pointed me to the actual problem: OhMyREPL

For some reason OhMyREPL wasn't allowing WebIO to be built correctly. After I commented out the line using OhMyREPL from my startup.jl file and restarted the notebook kernel, it worked!

JulioCFagundes commented 2 years ago

I did it and another error appeard, any idea of how to solve it?

Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any["a"], Dict{Symbol, Any}(:className => "interact ", :style => Dict{Any, Any}(:padding => "5px 10px 0px 10px")))], Dict{Symbol, Any}(:className => "interact-flex-row-left")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol, Any}(:max => 10, :min => 1, :attributes => Dict{Any, Any}(:type => "range", Symbol("data-bind") => "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}", "orient" => "horizontal"), :step => 1, :className => "slider slider is-fullwidth", :style => Dict{Any, Any}()))], Dict{Symbol, Any}(:className => "interact-flex-row-center")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol, Any}(:attributes => Dict("data-bind" => "text: formatted_val")))], Dict{Symbol, Any}(:className => "interact-flex-row-right"))], Dict{Symbol, Any}(:className => "interact-flex-row interact-widget")), Dict{String, Tuple{Observables.AbstractObservable, Union{Nothing, Bool}}}("changes" => (Observable{Int64} with 1 listeners. Value: 0, nothing), "index" => (Observable{Any} with 2 listeners. Value: 5, nothing)), Set{String}(), nothing, Asset[Asset("js", "knockout", "C:\Users\User\.julia\packages\Knockout\3gjS1\src\..\assets\knockout.js"), Asset("js", "knockout_punches", "C:\Users\User\.julia\packages\Knockout\3gjS1\src\..\assets\knockout_punches.js"), Asset("js", nothing, "C:\Users\User\.julia\packages\InteractBase\o1I6G\src\..\assets\all.js"), Asset("css", nothing, "C:\Users\User\.julia\packages\InteractBase\o1I6G\src\..\assets\style.css"), Asset("css", nothing, "C:\Users\User\.julia\packages\Interact\pVyN2\src\..\assets\bulma_confined.min.css")], Dict{Any, Any}("changes" => Any[WebIO.JSString("(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model\"changes\") : undefined})")], "index" => Any[WebIO.JSString("(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model\"index\") : undefined})")]), WebIO.ConnectionPool(Channel{Any}(32), Set{AbstractConnection}(), Condition(Base.InvasiveLinkedList{Task}(Task (runnable) @0x000000004f77c3f0, Task (runnable) @0x000000004f77c3f0), Base.AlwaysLockedST(1))), WebIO.JSString[WebIO.JSString("function () {\n var handler = (function (ko, koPunches) {\n ko.punches.enableAll();\n ko.bindingHandlers.numericValue = {\n init: function(element, valueAccessor, allBindings, data, context) {\n var stringified = ko.observable(ko.unwrap(valueAccessor()));\n stringified.subscribe(function(value) {\n var val = parseFloat(value);\n if (!isNaN(val)) {\n valueAccessor()(val);\n }\n });\n valueAccessor().subscribe(function(value) {\n var str = JSON.stringify(value);\n if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n return;\n if ([\"null\", \"\"].indexOf(str) >= 0)\n return;\n stringified(str);\n });\n ko.applyBindingsToNode(\n element,\n {\n value: stringified,\n valueUpdate: allBindings.get('valueUpdate'),\n },\n context,\n );\n }\n };\n var json_data = {\"formatted_vals\":[\"0.1\",\"0.144444\",\"0.188889\",\"0.233333\",\"0.277778\",\"0.322222\",\"0.366667\",\"0.411111\",\"0.455556\",\"0.5\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"15413358209832842711\",\"id\":\"12741283866794304884\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"15413358209832842711\",\"id\":\"6037025313322159793\",\"type\":\"observable\"})};\n var self = this;\n function AppViewModel() {\n for (var key in json_data) {\n var el = json_data[key];\n this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n }\n \n [this[\"formatted_val\"]=ko.computed( function(){\n return this.formatted_vals()[parseInt(this.index())-(1)];\n }\n,this)]\n [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"15413358209832842711\",\"id\":\"12741283866794304884\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"15413358209832842711\",\"id\":\"6037025313322159793\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n \n }\n self.model = new AppViewModel();\n self.valueFromJulia = {};\n for (var key in json_data) {\n self.valueFromJulia[key] = false;\n }\n ko.applyBindings(self.model, self.dom);\n}\n);\n (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/c2d59be8b1b2f7d7247a261dbf6ef29f39f8b21e-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/eb25b961942fa6a3b69e5d340ffc53183ea9189f-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n")])], Dict{Symbol, Any}(:className => "field interact-widget")), Observable{Node{WebIO.DOM}} with 0 listeners. Value: Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Plot{Plots.PlotlyBackend() n=1}], Dict{Symbol, Any}(:className => "interact-flex-row interact-widget"))], Dict{Symbol, Any}())

Heyuchen-330 commented 2 years ago

I'm facing the same problem, is there a solution already?