From 3c2cfa333c39b85155d6febd3818c534acf5f8ca Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 4 Oct 2018 15:20:21 +0200 Subject: [PATCH 1/5] allow to not host plotly from local file --- .gitignore | 1 + deps/build.jl | 23 +++++++++++++++----- src/Plots.jl | 6 ++++++ src/backends/plotly.jl | 49 +++++++++++++++++------------------------- src/backends/web.jl | 6 ++++++ src/init.jl | 17 +++++++++++++-- 6 files changed, 66 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 69fe281c..8b7142dd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ examples/.ipynb_checkpoints/* examples/meetup/.ipynb_checkpoints/* deps/plotly-latest.min.js deps/build.log +deps/deps.jl diff --git a/deps/build.jl b/deps/build.jl index ad328049..6993b263 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -1,8 +1,21 @@ #TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist - -local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") -if !isfile(local_fn) - @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") - download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) +file_path = "" +if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "true") == "true" + global file_path + local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") + if !isfile(local_fn) + @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") + download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) + @show local_fn isfile(local_fn) + if isfile(local_fn) + file_path = local_fn + end + else + file_path = local_fn + end +end + +open("deps.jl", "w") do io + println(io, "const plotly_local_file_path = $(repr(file_path))") end diff --git a/src/Plots.jl b/src/Plots.jl index 35b16001..8c4fd730 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -18,6 +18,12 @@ import JSON using Requires +if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) + include(joinpath(@__DIR__, "..", "deps", "deps.jl")) +else + error("Plots not build, please run Pkg.build(\"Plots\")") +end + export grid, bbox, diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3e525b5b..33a0d3f6 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -71,27 +71,22 @@ end # -------------------------------------------------------------------------------------- +const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js" - -const _plotly_js_path = joinpath(dirname(@__FILE__), "..", "..", "deps", "plotly-latest.min.js") -const _plotly_js_path_remote = "https://cdn.plot.ly/plotly-latest.min.js" - -_js_code = open(read, _plotly_js_path, "r") - -# borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 -_js_script = """ - -""" - -# if we're in IJulia call setupnotebook to load js and css -if isijulia() +if isfile(plotly_local_file_path) && isijulia() + _js_code = open(read, plotly_local_file_path, "r") + # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 + _js_script = """ + + """ + # if we're in IJulia call setupnotebook to load js and css display("text/html", _js_script) end @@ -102,8 +97,6 @@ end using UUIDs push!(_initialized_backends, :plotly) - - # ---------------------------------------------------------------- const _plotly_legend_pos = KW( @@ -115,7 +108,7 @@ const _plotly_legend_pos = KW( :bottomright => [1., 0.], :topright => [1., 1.], :topleft => [0., 1.] - ) +) plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.]) plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v @@ -882,11 +875,9 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) # ---------------------------------------------------------------- -const _use_remote = Ref(false) - function html_head(plt::Plot{PlotlyBackend}) - jsfilename = _use_remote[] ? _plotly_js_path_remote : ("file://" * _plotly_js_path) - # "" + local_file = ("file://" * plotly_local_file_path) + jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path "" end @@ -908,8 +899,8 @@ end function js_body(plt::Plot{PlotlyBackend}, uuid) js = """ - PLOT = document.getElementById('$(uuid)'); - Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt))); + PLOT = document.getElementById('$(uuid)'); + Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt))); """ end diff --git a/src/backends/web.jl b/src/backends/web.jl index 55984167..336cdeb0 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -42,8 +42,14 @@ function write_temp_html(plt::AbstractPlot) end function standalone_html_window(plt::AbstractPlot) + old = use_local_dependencies[] # save state to restore afterwards + # if we open a browser ourself, we can host local files, so we + # when we have a local plotly downloaded this is the way to go! + use_local_dependencies[] = isfile(plotly_local_file_path) filename = write_temp_html(plt) open_browser_window(filename) + # restore for other backends + use_local_dependencies[] = old end # uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html diff --git a/src/init.jl b/src/init.jl index 08d1dd2b..fd6fce03 100644 --- a/src/init.jl +++ b/src/init.jl @@ -1,4 +1,7 @@ +const use_local_dependencies = Ref(false) + function __init__() + if isdefined(Main, :PLOTS_DEFAULTS) if haskey(Main.PLOTS_DEFAULTS, :theme) theme(Main.PLOTS_DEFAULTS[:theme]) @@ -27,10 +30,11 @@ function __init__() # --------------------------------------------------------- # IJulia # --------------------------------------------------------- - + use_local = false @require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin if IJulia.inited - + # IJulia is more stable with local file + use_local = isfile(plotly_local_file_path) """ Add extra jupyter mimetypes to display_dict based on the plot backed. @@ -80,4 +84,13 @@ function __init__() ENV["MPLBACKEND"] = "Agg" end end + if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL") + use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true" + use_local_dependencies[] = isfile(plotly_local_file_path) && use_local + if use_local && !isfile(plotly_local_file_path) + @warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true") + end + else + use_local_dependencies[] = use_local + end end From f5de5f58ce89f3337596a7bfc3e7ffc760e349db Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 4 Oct 2018 15:39:59 +0200 Subject: [PATCH 2/5] make ijulia plotly integration precompile save --- src/backends/plotly.jl | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 33a0d3f6..60d01669 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -73,22 +73,6 @@ end # -------------------------------------------------------------------------------------- const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js" -if isfile(plotly_local_file_path) && isijulia() - _js_code = open(read, plotly_local_file_path, "r") - # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 - _js_script = """ - - """ - # if we're in IJulia call setupnotebook to load js and css - display("text/html", _js_script) -end # if isatom() # import Atom @@ -875,7 +859,26 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) # ---------------------------------------------------------------- +const ijulia_initialized = Ref(false) + function html_head(plt::Plot{PlotlyBackend}) + if isfile(plotly_local_file_path) && isijulia() && !ijulia_initialized[] + js_code = read(plotly_local_file_path, String) + # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 + js_script = """ + + """ + # if we're in IJulia call setupnotebook to load js and css + display("text/html", js_script) + ijulia_initialized[] = true + end local_file = ("file://" * plotly_local_file_path) jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path "" From ee4fc2803b489e9aa9ae30b0d1c409316657ca56 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:27:01 +0200 Subject: [PATCH 3/5] dont download by default --- deps/build.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/deps/build.jl b/deps/build.jl index 6993b263..a8cf81ff 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -1,16 +1,13 @@ #TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist file_path = "" -if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "true") == "true" +if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true" global file_path local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js") if !isfile(local_fn) @info("Cannot find deps/plotly-latest.min.js... downloading latest version.") download("https://cdn.plot.ly/plotly-latest.min.js", local_fn) - @show local_fn isfile(local_fn) - if isfile(local_fn) - file_path = local_fn - end + isfile(local_fn) && (file_path = local_fn) else file_path = local_fn end From 7e0960e7a0d6a2ca1bee980916104b45a98b50db Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:27:09 +0200 Subject: [PATCH 4/5] fix IJulia --- src/Plots.jl | 6 +++++- src/backends/plotly.jl | 30 ++++++++++++++---------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 8c4fd730..6f40334f 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -21,7 +21,11 @@ using Requires if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) include(joinpath(@__DIR__, "..", "deps", "deps.jl")) else - error("Plots not build, please run Pkg.build(\"Plots\")") + # This is a bit dirty, but I don't really see why anyone should be forced + # to build Plots, while it will just include exactly the below line + # as long as now ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true" is given + # If the above env is set + plotly_local_file_path = "", it will warn in the __init__ functtion + const plotly_local_file_path = "" end export diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 60d01669..5c12ba4b 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -862,26 +862,24 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt)) const ijulia_initialized = Ref(false) function html_head(plt::Plot{PlotlyBackend}) - if isfile(plotly_local_file_path) && isijulia() && !ijulia_initialized[] - js_code = read(plotly_local_file_path, String) - # borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2 - js_script = """ - - """ - # if we're in IJulia call setupnotebook to load js and css - display("text/html", js_script) + """) ijulia_initialized[] = true end - local_file = ("file://" * plotly_local_file_path) - jsfilename = use_local_dependencies[] ? local_file : plotly_remote_file_path - "" + # IJulia just needs one initialization + isijulia() && return "" + return "" end function html_body(plt::Plot{PlotlyBackend}, style = nothing) From 9ccb699fca1add6201ad3ddada095971b6597cd5 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 5 Oct 2018 12:33:13 +0200 Subject: [PATCH 5/5] improve comments --- src/Plots.jl | 5 +++-- src/backends/web.jl | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 6f40334f..448bdfec 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -23,8 +23,9 @@ if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl")) else # This is a bit dirty, but I don't really see why anyone should be forced # to build Plots, while it will just include exactly the below line - # as long as now ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true" is given - # If the above env is set + plotly_local_file_path = "", it will warn in the __init__ functtion + # as long as `ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true"` is not set. + # If the above env is set + `plotly_local_file_path == ""``, + # it will warn in the __init__ function to run build const plotly_local_file_path = "" end diff --git a/src/backends/web.jl b/src/backends/web.jl index 336cdeb0..b1663435 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -43,7 +43,7 @@ end function standalone_html_window(plt::AbstractPlot) old = use_local_dependencies[] # save state to restore afterwards - # if we open a browser ourself, we can host local files, so we + # if we open a browser ourself, we can host local files, so # when we have a local plotly downloaded this is the way to go! use_local_dependencies[] = isfile(plotly_local_file_path) filename = write_temp_html(plt)