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

Convert Requires based providers to Pkg extensions #516

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/documenter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ jobs:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
version: '1.6'
version: '1.10'
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key
run: julia --project=docs/ docs/make.jl
run: julia --project=docs/ docs/make.jl
19 changes: 5 additions & 14 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,23 @@ jobs:
fail-fast: false
matrix:
version:
- '1.6' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1.10' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- 'nightly'
os:
- ubuntu-latest
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: '16'
- uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ coverage/
*.jl.cov
*.jl.*.cov
*.jl.mem
docs/src/assets/trivial_import.js

# JavaScript
dist
Expand Down
31 changes: 13 additions & 18 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,28 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Observables = "510215fc-4207-5dde-b226-833fc4488ee2"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
WebSockets = "104b5d7c-a370-577a-8038-80a2059c5097"
Widgets = "cc8bc4a8-27d6-5769-a93b-9d913e69aa62"

[weakdeps]
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
Mux = "a975b10e-0019-58db-a62f-e48ff68538c9"
WebSockets = "104b5d7c-a370-577a-8038-80a2059c5097"

[extensions]
IJuliaExt = "IJulia"
MuxExt = "Mux"
WebSocketsExt = "WebSockets"

[compat]
AssetRegistry = "0.1.0"
FunctionalCollections = "0.5.0"
JSExpr = "0.5"
IJulia = "1.13"
JSON = "0.18, 0.19, 0.20, 0.21"
Mux = "1"
Observables = "0.5"
Requires = "0.4.4, 0.5, 1.0.0"
WebSockets = "1.5.0, 1.6.0"
Widgets = "0.6.2"
julia = "1.6"

[extras]
Blink = "ad839575-38b3-5650-b840-f874b8c74a25"
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
JSExpr = "97c1335a-c9c5-57fe-bc5d-ec35cebe8660"
Mux = "a975b10e-0019-58db-a62f-e48ff68538c9"
NBInclude = "0db19996-df87-5ea3-a455-e3a50d440464"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
julia = "1.10"

[targets]
test = ["Blink", "Conda", "DataStructures", "Dates", "IJulia", "JSExpr", "Mux", "NBInclude", "Test"]
11 changes: 0 additions & 11 deletions deps/jupyter.jl

This file was deleted.

7 changes: 7 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ Blink = "ad839575-38b3-5650-b840-f874b8c74a25"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
Mux = "a975b10e-0019-58db-a62f-e48ff68538c9"
WebIO = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29"

[compat]
Blink = "0.12"
Documenter = "1.8"
IJulia = "1.13"
Mux = "1"
23 changes: 22 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
using Documenter
using Documenter, SHA
using WebIO

# Copy or update trivial_import.js
docs_trivial_path = joinpath(@__DIR__, "src/assets/trivial_import.js")
test_trivial_path = joinpath(@__DIR__, "../test/assets/trivial_import.js")
if isfile(docs_trivial_path)
test_sha = open(test_trivial_path) do io
sha1(io)
end
docs_sha = open(docs_trivial_path) do io
sha1(io)
end
if test_sha != docs_sha
cp(test_trivial_path, docs_trivial_path; force=true)
end
else
mkdir(dirname(docs_trivial_path))
cp(test_trivial_path, docs_trivial_path)
end

# We have to ensure that these modules are loaded because some functions are
# defined behind @require guards.
using IJulia, Mux, Blink

DocMeta.setdocmeta!(WebIO, :DocTestSetup, :(using WebIO); recursive=true)

makedocs(
sitename="WebIO",
warnonly=true,
format=Documenter.HTML(),
modules=[WebIO],
pages=[
Expand Down
14 changes: 14 additions & 0 deletions docs/src/assets/trivial_import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// A trivial importable module that simply produces "ok".
// Used for testing the WebIO Scope imports machinery.

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else {
// Browser globals
root.amdWeb = factory();
}
}(typeof self !== 'undefined' ? self : this, function () {
return {x: "ok"}
}));
24 changes: 14 additions & 10 deletions src/providers/ijulia.jl → ext/IJuliaExt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using .AssetRegistry
using .Sockets
using .WebIO
module IJuliaExt

using WebIO
using WebIO: WEBIO_NODE_MIME
using IJulia, Sockets

struct IJuliaConnection <: AbstractConnection
comm::IJulia.CommManager.Comm
Expand Down Expand Up @@ -68,16 +70,18 @@ function main()
return
end

# https://github.com/JuliaLang/IJulia.jl/pull/755
if isdefined(IJulia, :register_jsonmime)
IJulia.register_jsonmime(WEBIO_NODE_MIME())
else
@warn "IJulia doesn't have register_mime; WebIO may not work as expected. Please upgrade to IJulia v1.13.0 or greater."
end
IJulia.register_jsonmime(WEBIO_NODE_MIME())

# See comment on _IJuliaInit for what this does
display(_IJuliaInit())

return nothing
end

WebIO.setup_provider(::Val{:ijulia}) = main() # calling setup_provider(Val(:ijulia)) will display the setup javascript
WebIO.setup(:ijulia)

function __init__()
WebIO.setup(:ijulia)
end

end
30 changes: 20 additions & 10 deletions src/providers/mux.jl → ext/MuxExt.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
using .JSON
using .AssetRegistry
using .Sockets
using .Base64: stringmime
export webio_serve
module MuxExt

using WebIO
using WebIO: MUX_BUNDLE_PATH

using Mux, JSON, AssetRegistry
using Sockets
using Base64: stringmime

"""
webio_serve(app, port=8000)

Serve a Mux app which might return a WebIO node.
"""
function webio_serve(app, args...)
function WebIO.webio_serve(app, args...)
http = Mux.App(Mux.mux(
Mux.defaults,
app,
Mux.notfound()
))
webio_serve(http, args...)
WebIO.webio_serve(http, args...)
end
function webio_serve(app::Mux.App, args...)
function WebIO.webio_serve(app::Mux.App, args...)
websock = Mux.App(Mux.mux(
Mux.wdefaults,
Mux.route("/webio-socket", create_socket),
Expand Down Expand Up @@ -53,7 +56,9 @@ end

Base.isopen(p::WebSockConnection) = isopen(p.sock)

Mux.Response(o::AbstractWidget) = Mux.Response(Widgets.render(o))
# TYPE-PIRACY
# Mux.Response(o::AbstractWidget) = Mux.Response(Widgets.render(o))

function Mux.Response(content::Union{Node, Scope})
script_url = try
AssetRegistry.register(MUX_BUNDLE_PATH)
Expand Down Expand Up @@ -86,4 +91,9 @@ function WebIO.register_renderable(::Type{T}, ::Val{:mux}) where {T}
end

WebIO.setup_provider(::Val{:mux}) = nothing # Mux setup has no side-effects
WebIO.setup(:mux)

function __init__()
WebIO.setup(:mux)
end

end
56 changes: 26 additions & 30 deletions src/providers/generic_http.jl → ext/WebSocketsExt.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using .Sockets
import .AssetRegistry, .JSON
using .WebIO
using .WebSockets: is_upgrade, upgrade, writeguarded
using .WebSockets: HTTP
module WebSocketsExt

using WebIO, JSON, AssetRegistry
using Sockets

using WebIO: WEBIO_APPLICATION_MIME, GENERIC_HTTP_BUNDLE_PATH, bundle_key,
global_server_config, WebIOServer, singleton_instance, routing_callback,
webio_server_config
using WebSockets: WebSockets, HTTP, is_upgrade, upgrade, writeguarded

struct WSConnection{T} <: WebIO.AbstractConnection
sock::T
Expand All @@ -12,15 +15,7 @@ end
Sockets.send(p::WSConnection, data) = writeguarded(p.sock, JSON.json(data))
Base.isopen(p::WSConnection) = isopen(p.sock)

if !isfile(GENERIC_HTTP_BUNDLE_PATH)
error(
"Unable to find WebIO JavaScript bundle for generic HTTP provider; "
* "try rebuilding WebIO (via `Pkg.build(\"WebIO\")`)."
)
end
const bundle_key = AssetRegistry.register(GENERIC_HTTP_BUNDLE_PATH)

include(joinpath(@__DIR__, "..", "..", "deps", "mimetypes.jl"))
include(joinpath(@__DIR__, "..", "deps", "mimetypes.jl"))

"""
Serve an asset from the asset registry.
Expand Down Expand Up @@ -52,17 +47,8 @@ function websocket_handler(ws)
end
end

struct WebIOServer{S}
server::S
serve_task::Task
end

kill!(server::WebIOServer) = put!(server.server.in, HTTP.Servers.KILL)

const singleton_instance = Ref{WebIOServer}()

const routing_callback = Ref{Any}((req)-> missing)

"""
Run the WebIO server.

Expand All @@ -84,7 +70,7 @@ end
server = WebIO.WebIOServer(serve_app, verbose = true)
```
"""
function WebIOServer(
function WebIO.WebIOServer(
default_response::Function = (req)-> missing;
baseurl::String = "127.0.0.1", http_port::Int = 8081,
verbose = false, singleton = true,
Expand All @@ -111,7 +97,7 @@ function WebIOServer(
else # relative url
string("http://", baseurl, ":", http_port, WebIO.baseurl[])
end
string(base, bundle_key)
string(base, bundle_key[])
end
wait_time = 5; start = time() # wait for max 5 s
while time() - start < wait_time
Expand All @@ -127,24 +113,22 @@ function WebIOServer(
return singleton_instance[]
end

const webio_server_config = Ref{typeof((url = "", bundle_url = "", http_port = 0, ws_url = ""))}()

"""
Fetches the global configuration for our http + websocket server from environment
variables. It will memoise the result, so after a first call, any update to
the environment will get ignored.
"""
function global_server_config()
function WebIO.global_server_config()
if !isassigned(webio_server_config)

setbaseurl!(get(ENV, "JULIA_WEBIO_BASEURL", ""))
WebIO.setbaseurl!(get(ENV, "JULIA_WEBIO_BASEURL", ""))

url = get(ENV, "WEBIO_SERVER_HOST_URL", "127.0.0.1")
http_port = parse(Int, get(ENV, "WEBIO_HTTP_PORT", "8081"))
ws_default = string("ws://", url, ":", http_port, "/webio_websocket/")
ws_url = get(ENV, "WEBIO_WEBSOCKT_URL", ws_default)
# make it possible, to e.g. host the bundle online
bundle_url = get(ENV, "WEBIO_BUNDLE_URL", string(WebIO.baseurl[], bundle_key))
bundle_url = get(ENV, "WEBIO_BUNDLE_URL", string(WebIO.baseurl[], bundle_key[]))
webio_server_config[] = (
url = url, bundle_url = bundle_url,
http_port = http_port, ws_url = ws_url
Expand Down Expand Up @@ -176,3 +160,15 @@ function Base.show(io::IO, m::WEBIO_APPLICATION_MIME, app::Application)
show(io, "text/html", app)
return
end

function __init__()
if !isfile(GENERIC_HTTP_BUNDLE_PATH)
error(
"Unable to find WebIO JavaScript bundle for generic HTTP provider; "
* "try rebuilding WebIO (via `Pkg.build(\"WebIO\")`)."
)
end
bundle_key[] = AssetRegistry.register(GENERIC_HTTP_BUNDLE_PATH)
end

end
Loading
Loading