Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bad deprecation for Scope constructor. #308

Merged
merged 1 commit into from
Jun 10, 2019

Conversation

twavv
Copy link
Member

@twavv twavv commented Jun 10, 2019

Fixes JuliaGizmos/Interact.jl#315.

The problematic bit of code seems to be this line in Knockout.jl.

@twavv
Copy link
Member Author

twavv commented Jun 10, 2019

Thanks to @AshtonSBradley for pointing this out and being just generally a helpful person™. Will release v0.8.5 when CI passes.

@codecov
Copy link

codecov bot commented Jun 10, 2019

Codecov Report

Merging #308 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #308   +/-   ##
=======================================
  Coverage   57.49%   57.49%           
=======================================
  Files          17       17           
  Lines         614      614           
=======================================
  Hits          353      353           
  Misses        261      261
Impacted Files Coverage Δ
src/scope.jl 61.11% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b44d600...85048be. Read the comment docs.

@twavv twavv merged commit 8353da3 into master Jun 10, 2019
@SimonDanisch SimonDanisch deleted the td/fix-scope-constructor-deprecation branch June 10, 2019 17:17
@ClaudMor
Copy link

ClaudMor commented Apr 24, 2020

I still have this issue:

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[125]:1
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-7700HQ CPU @ 2.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
Environment:
  JULIA_DEPOT_PATH = \userpath\.juliapro\JuliaPro_v1.4.1-1;D:\JuliaPro\juliapro\Julia-1.4.1\local\share\julia;D:\JuliaPro\juliapro\Julia-1.4.1\share\julia
  JULIA_EDITOR = "D:\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 ⚲
  [5ae59095] Colors v0.11.2
  [7073ff75] IJulia v1.21.1
  [c601a237] Interact v0.10.3
  [e5e0dc1b] Juno v0.8.1 ⚲
  [4722fa14] PkgAuthentication v0.1.2
  [24249f21] SymPy v1.0.18
  [44d3d7a6] Weave v0.9.4
  [37e2e46d] LinearAlgebra
(@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
  [e66e0078] CompilerSupportLibraries_jll v0.3.3+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
  [efe28fd5] OpenSpecFun_jll v0.5.3+3
  [bac558e1] OrderedCollections v1.1.0
  [69de0a69] Parsers v1.0.1
  [fa939f87] Pidfile v1.1.0
  [4722fa14] PkgAuthentication v0.1.2
  [438e738f] PyCall v1.91.4
  [3cdcf5f2] RecipesBase v0.7.0
  [189a3867] Reexport v0.2.0
  [ae029012] Requires v1.0.1
  [b85f4697] SoftGlobalScope v1.0.10
  [276daf66] SpecialFunctions v0.10.0
  [88034a9c] StringDistances v0.6.3
  [24249f21] SymPy v1.0.18
  [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

EDIT: the issue exists both on Juno and on jupyter lab.
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

@twavv
Copy link
Member Author

twavv commented Apr 25, 2020

Your issue is unrelated to this PR. Please open a new issue.

@ClaudMor
Copy link

Ok, I opened another issue here. Sorry for the confusion. Should I delete the comment above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@manipulate broken
2 participants