diff --git a/Artifacts.toml b/Artifacts.toml index 17ffe66..54b4845 100644 --- a/Artifacts.toml +++ b/Artifacts.toml @@ -1,6 +1,6 @@ [dash_resources] -git-tree-sha1 = "c857e355d2c21dfc458fb315371431dda2506109" +git-tree-sha1 = "cf73063fdfc374bc98925f87ac967051cdee66e5" [[dash_resources.download]] - sha256 = "4ff3910a8ff1f5420784397cfc6ad80341bbe03f1010eab38dcb9b8ce2423310" - url = "https://github.com/plotly/DashCoreResources/releases/download/v2.0.0+0/DashCoreResources.v2.0.0.tar.gz" + sha256 = "c0fda20e816034b8f97f779af8b3081d3578164649d9ff6c21a8146d4af52d96" + url = "https://github.com/plotly/DashCoreResources/releases/download/v2.10.2+0/DashCoreResources.v2.10.2.tar.gz" diff --git a/gen_resources/Project.toml b/gen_resources/Project.toml index f1667b5..1fdfc5a 100644 --- a/gen_resources/Project.toml +++ b/gen_resources/Project.toml @@ -5,6 +5,7 @@ HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" +OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" diff --git a/gen_resources/README.md b/gen_resources/README.md new file mode 100644 index 0000000..5ab47a7 --- /dev/null +++ b/gen_resources/README.md @@ -0,0 +1,88 @@ +# Generate Dash.jl artifacts + +Dash.jl uses Julia +[Artifacts](https://docs.julialang.org/en/v1/stdlib/Artifacts/) to load +front-end resources that Dash.jl shares with the python version of +[dash](https://github.com/plotly/dash). + +The [Artifacts.toml](../Artifacts.toml) file lists the location of the +publicly-available tarball containing all the required resources. + +The tarballs are hosted on the +[DashCoreResources](https://github.com/plotly/DashCoreResources) repo, under +_Releases_. They are generated and deployed using the `generate.jl` script in +this directory. + +## How to run `generate.jl` ? + +### Step 0: get push rights to `DashCoreResources` + +### Step 1: get GitHub personal access token + +See [GitHub docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token) +for more info. + +If using a fine-grained token, make sure to enable _Read and Write access to code_. + +### Step 2: expose your token into your shell + +```sh +# for example: +export GITHUB_TOKEN="" +``` + +### Step 3: run `generate.jl` + +```sh +cd Dash.jl/gen_resources + +# install `generate.jl` deps +julia --project -e 'import Pkg; Pkg.instantiate()' + +# generate `gen_resources/build/deploy/` content, +# but do not deploy! +julia --project generate.jl + +# if everything looks fine, +# generate `gen_resources/build/deploy/` content (again) and +# deploy to the `DashCoreResource` releases with: +julia --project generate.jl --deploy +``` + +#### If `generate.jl` errors + +
+with a PyError / PyImport error + +that is an error like: + +```sh +ERROR: LoadError: PyError (PyImport_ImportModule + +The Python package dash could not be imported by pyimport. Usually this means +that you did not install dash in the Python version being used by PyCall. + +PyCall is currently configured to use the Python version at: + +/usr/bin/python3 +``` + +try + +```jl +using PyCall +ENV["PYTHON"] = joinpath(homedir(), ".julia/conda/3/x86_64/bin") +import Pkg +Pkg.build("PyCall") +# check that it matches with +PyCall.pyprogramname +``` + +and then re-run `generate.jl`. + +
+ +### Step 4: Commit the changes to `Artifacts.toml` + +and push to [plotly/Dash.jl](https://github.com/plotly/Dash.jl) +(preferably on a new branch) to get a CI test run started. diff --git a/gen_resources/Sources.toml b/gen_resources/Sources.toml index d52ac9e..e993607 100644 --- a/gen_resources/Sources.toml +++ b/gen_resources/Sources.toml @@ -2,9 +2,9 @@ repo = "plotly/DashCoreResources" [dash] url = "https://github.com/plotly/dash.git" - tag = "v2.0.0" + tag = "v2.10.2" [dash_renderer] - module = "dash_renderer" + module = "dash._dash_renderer" resources_path = "." [components] [components.dash_html_components] diff --git a/gen_resources/generator/dash.jl b/gen_resources/generator/dash.jl index 4fcc538..fe006fc 100644 --- a/gen_resources/generator/dash.jl +++ b/gen_resources/generator/dash.jl @@ -1,7 +1,7 @@ """ install_dash(url, tag) -Clone python dash into `dash` folder and install (reinstall) it to current python enviroment +Clone python dash into `dash` folder and install (reinstall) it to current python environment """ function install_dash(url, tag) Conda.pip_interop(true) diff --git a/gen_resources/generator/github.jl b/gen_resources/generator/github.jl index df14ed1..1fe38a5 100644 --- a/gen_resources/generator/github.jl +++ b/gen_resources/generator/github.jl @@ -10,7 +10,7 @@ const _github_auth = Ref{GitHub.Authorization}() function github_auth(;allow_anonymous::Bool=true) if !isassigned(_github_auth) || !allow_anonymous && isa(_github_auth[], GitHub.AnonymousAuth) # If the user is feeding us a GITHUB_TOKEN token, use it! - if length(get(ENV, "GITHUB_TOKEN", "")) == 40 + if length(get(ENV, "GITHUB_TOKEN", "")) >= 40 _github_auth[] = GitHub.authenticate(ENV["GITHUB_TOKEN"]) else if allow_anonymous diff --git a/src/init/resources.jl b/src/init/resources.jl index 86b8bbd..028c532 100644 --- a/src/init/resources.jl +++ b/src/init/resources.jl @@ -23,33 +23,28 @@ dash_module_resource(meta) = Resource( async = haskey(meta, "async") ? string(meta["async"]) : nothing ) -dash_module_resource_pkg(meta; resource_path, version) = ResourcePkg( - meta["namespace"], - resource_path, version = version, - dash_module_resource.(meta["resources"]) -) - function setup_renderer_resources() renderer_meta = _metadata.dash_renderer renderer_resource_path = joinpath(artifact"dash_resources", "dash_renderer_deps") + renderer_version = renderer_meta["version"] DashBase.main_registry().dash_dependency = ( dev = ResourcePkg( "dash_renderer", - renderer_resource_path, version = renderer_meta["version"], + renderer_resource_path, version = renderer_version, dash_dependency_resource.(renderer_meta["js_dist_dependencies"]["dev"]) ), prod = ResourcePkg( "dash_renderer", - renderer_resource_path, version = renderer_meta["version"], + renderer_resource_path, version = renderer_version, dash_dependency_resource.(renderer_meta["js_dist_dependencies"]["prod"]) ) ) - - DashBase.main_registry().dash_renderer = dash_module_resource_pkg( - renderer_meta["deps"][1], - resource_path = renderer_resource_path, - version = renderer_meta["version"] - ) + renderer_renderer_meta = renderer_meta["deps"][1] + DashBase.main_registry().dash_renderer = ResourcePkg( + "dash_renderer", + renderer_resource_path, version = renderer_version, + dash_module_resource.(renderer_renderer_meta["resources"]) + ) end function load_all_metadata() @@ -72,10 +67,11 @@ function setup_dash_resources() version = meta["version"] for dep in meta["deps"] DashBase.register_package( - dash_module_resource_pkg( - dep, - resource_path = path, - version = version + ResourcePkg( + dep["namespace"], + path, + version = version, + dash_module_resource.(dep["resources"]) ) ) end diff --git a/test/integration/clientside/test_clientside.py b/test/integration/clientside/test_clientside.py index 91a9992..2dd62de 100644 --- a/test/integration/clientside/test_clientside.py +++ b/test/integration/clientside/test_clientside.py @@ -95,13 +95,13 @@ def test_jlclsd004_clientside_multiple_outputs(dashjl): ]: dashjl.wait_for_text_to_equal(selector, expected, timeout=10) -def test_jlclsd005_clientside_fails_when_returning_a_promise(dashjl): +def test_jlclsd005_clientside_when_returning_a_promise(dashjl): fp = jl_test_file_path("jlclsd005_clientside_fails_when_returning_a_promise.jl") dashjl.start_server(fp) dashjl.wait_for_text_to_equal("#input", "hello", timeout=10) dashjl.wait_for_text_to_equal("#side-effect", "side effect") - dashjl.wait_for_text_to_equal("#output", "output") + dashjl.wait_for_text_to_equal("#output", "foo") def test_jlclsd006_PreventUpdate(dashjl): fp = jl_test_file_path("jlclsd006_PreventUpdate.jl") diff --git a/test/integration/devtools/jl_props_check/jldvpc001_prop_check_errors_with_path.jl b/test/integration/devtools/jl_props_check/jldvpc001_prop_check_errors_with_path.jl index 8b98907..2643779 100644 --- a/test/integration/devtools/jl_props_check/jldvpc001_prop_check_errors_with_path.jl +++ b/test/integration/devtools/jl_props_check/jldvpc001_prop_check_errors_with_path.jl @@ -13,12 +13,6 @@ test_cases = Dict( "component"=> dcc_checklist, "props"=> (options = [Dict("label" => "hello")], value = ["test"]), ), - "invalid-nested-prop"=> Dict( - "fail"=> true, - "name"=> "invalid nested prop", - "component"=> dcc_checklist, - "props"=> (options = [Dict("label"=> "hello", "value"=> true)], value = ["test"]), - ), "invalid-arrayOf"=> Dict( "fail"=> true, "name"=> "invalid arrayOf", @@ -73,6 +67,12 @@ test_cases = Dict( "component"=> html_div, "props"=> (children = Dict("hello" => "world"),), ), + "allow-nested-prop"=> Dict( + "fail"=> false, + "name"=> "allow nested prop", + "component"=> dcc_checklist, + "props"=> (options = [Dict("label"=> "hello", "value"=> true)], value = ["test"]), + ), "allow-null-2"=> Dict( "fail"=> false, "name"=> "allow null as value", diff --git a/test/integration/devtools/test_props_check.py b/test/integration/devtools/test_props_check.py index d6342d3..2099a70 100644 --- a/test/integration/devtools/test_props_check.py +++ b/test/integration/devtools/test_props_check.py @@ -16,10 +16,6 @@ def jl_test_file_path(filename): "fail": True, "name": 'missing required "value" inside options', }, - "invalid-nested-prop": { - "fail": True, - "name": "invalid nested prop", - }, "invalid-arrayOf": { "fail": True, "name": "invalid arrayOf", @@ -56,6 +52,10 @@ def jl_test_file_path(filename): "fail": True, "name": "returning a dictionary", }, + "allow-nested-prop": { + "fail": False, + "name": "allow nested prop", + }, "allow-null-2": { "fail": False, "name": "allow null as value", @@ -99,6 +99,7 @@ def test_jldvpc001_prop_check_errors_with_path(dashjl): if test_cases[tc]["fail"]: dashjl.wait_for_element(".test-devtools-error-toggle", timeout=10).click() - dashjl.wait_for_element(".dash-error-card") + dashjl.wait_for_element(".dash-fe-error__info") else: dashjl.wait_for_element("#new-component", timeout=2) + dashjl.wait_for_no_elements(".test-devtools-error-toggle")