Skip to content

Commit

Permalink
Merge pull request #21 from meggart/main
Browse files Browse the repository at this point in the history
WIP: Use structs instead of modules to namespace Connections
  • Loading branch information
danlooo authored Dec 19, 2023
2 parents 066191c + 3af62f7 commit 46d7dde
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 85 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
Infiltrator = "5903a43b-9cc3-4c30-8d17-598619ec4e9b"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
Expand Down
78 changes: 35 additions & 43 deletions src/Connections.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ end
"OpenID Connect device flow + PKCE authentification"
function AuthorizedConnection(host, version)
provider = fetchApi("https://$(host)/$(version)/credentials/oidc").providers[1]
discovery_url = "$(provider.issuer).well-known/openid-configuration"
if endswith(provider.issuer, "/")
discovery_url = "$(provider.issuer).well-known/openid-configuration"
else
discovery_url = "$(provider.issuer)/.well-known/openid-configuration"
end
client_id = provider.default_clients[1].id
scopes = provider.scopes
access_token = get_acces_token(discovery_url, client_id, scopes)
Expand Down Expand Up @@ -123,55 +127,43 @@ function fetchApi(connection::AuthorizedConnection, path::String; headers=deepco
return response
end

function connect(host, version, auth_method::AuthMethod=no_auth)
processes_code = get_processes_code(host, version)
struct ConnectionInstance
connection::AbstractConnection
collections::Vector
processes::Dict{Symbol}
end
Base.Docs.Binding(x::ConnectionInstance,s::Symbol) = getproperty(x,s)
Base.propertynames(i::ConnectionInstance,_::Bool=false) = [collect(keys(getfield(i,:processes)));:compute_result]
function Base.getproperty(i::ConnectionInstance,k::Symbol)
if k in (:connection,:connections,:processes)
getfield(i,k)
elseif k==:compute_result
Base.Fix1(compute_result,getfield(i,:connection))
else
getfield(i,:processes)[k]
end
end

if auth_method == no_auth
module_str = """
module Connection$(n_existing_connections)
using OpenEOClient
const connection = OpenEOClient.UnAuthorizedConnection("$host", "$version")
const collections = OpenEOClient.list_collections(connection)
const processes = OpenEOClient.list_processes(connection)

$processes_code
end
"""
function connect(host, version, auth_method::AuthMethod=no_auth)
connection = if auth_method == no_auth
OpenEOClient.UnAuthorizedConnection("$host", "$version")
elseif auth_method == oidc_auth
module_str = """
module Connection$(n_existing_connections)
using OpenEOClient
const connection = OpenEOClient.AuthorizedConnection("$host", "$version")
const collections = OpenEOClient.list_collections(connection)
const processes = OpenEOClient.list_processes(connection)
compute_result(p) = OpenEOClient.compute_result(connection, p)
$processes_code
end
"""
OpenEOClient.AuthorizedConnection("$host", "$version")
end

global n_existing_connections += 1
eval(Meta.parse(module_str))
connect(connection)
end

function connect(host, version::String, username::String, password::String)
access_response = fetchApi("https://$(username):$(password)@$(host)/$(version)/credentials/basic")
access_token = access_response["access_token"]
processes_code = get_processes_code(host, version)

module_str = """
module Connection$(n_existing_connections)
using OpenEOClient
const connection = OpenEOClient.AuthorizedConnection("$host", "$version", "Bearer basic//$access_token")
const collections = OpenEOClient.list_collections(connection)
const processes = OpenEOClient.list_processes(connection)
compute_result(p) = OpenEOClient.compute_result(connection, p)
$processes_code
end
"""
connection = OpenEOClient.AuthorizedConnection("$host", "$version", "Bearer basic//$access_token")
connect(connection)
end

global n_existing_connections += 1
eval(Meta.parse(module_str))
end
function connect(connection::AbstractConnection)
collections = OpenEOClient.list_collections(connection)
processes = OpenEOClient.list_processes(connection)
processesdict = Dict(Symbol(p.id) => p for p in processes)
ConnectionInstance(connection,collections,processesdict)
end
5 changes: 3 additions & 2 deletions src/ProcessGraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ function compute_result(connection::AuthorizedConnection, process_graph::Process
file_extension = split(Dict(response.headers)["Content-Type"], "/")[2]
filepath = "out." * file_extension
end

write(open(filepath, "w"), response.body)
open(filepath, "w") do f
write(f, response.body)
end
return filepath
end

Expand Down
62 changes: 22 additions & 40 deletions src/Processes.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using HTTP
import StructTypes
import Base64: base64encode
import Markdown

struct ProcessParameter
name::String
Expand All @@ -26,6 +27,26 @@ struct Process
experimental::Union{Nothing,Bool}
end
StructTypes.StructType(::Type{Process}) = StructTypes.Struct()
function (process::Process)(args...)
params = get_parameters(process.parameters)
length(args) == length(params) || throw(ArgumentError("Number of arguments does not match for process $(process.id)"))
argument_dict = Dict{Symbol,Any}()
for i in 1:length(args)
argname,argtype = params[i]
args[i] isa argtype || throw(ArgumentError("Type of argument number $i does not match, expected $argtype but got $(typeof(args[i]))"))
argument_dict[argname] = args[i]
end
ProcessNode("$(process.id)", argument_dict)
end
function Docs.getdoc(process::Process)
arguments = get_parameters(process.parameters)
args_str = join(["$(k)::$(v)" for (k, v) in arguments], ", ")
docs = """ $(process.id)($(args_str))
$(process.description)
"""
Markdown.parse(docs)
end
Base.Docs.doc(p::Process, ::Type = Union{}) = Base.Docs.getdoc(p)

function Base.show(io::IO, ::MIME"text/plain", p::Process)
print(io, "$(p.id)($(join([x.name for x in p.parameters], ", "))): $(p.summary)")
Expand Down Expand Up @@ -144,49 +165,10 @@ function get_parameters(parameters)
end
end
julia_types = [get(julia_types_map, t, String) for t in types]
julia_type = eval(Meta.parse("Union{" * join(julia_types, ",") * "}"))
julia_type = Union{julia_types...}

push!(res, name => julia_type)
end
return res
end

function get_processes_code(host, version)
connection = UnAuthorizedConnection(host, version)
processes = list_processes(connection)
processes_codes = []
warnings = []
for process in processes
try
arguments = get_parameters(process.parameters)
args_str = join(["$(k)::$(v)" for (k, v) in arguments], ", ")
args_dict_str = join([":$k=>$k" for (k, v) in arguments], ", ")
docs = [
" $(process.id)($(args_str))",
process.description
]
doc_str = join(docs, "\n\n") |> escape_string

code = """
\"\"\"
$(doc_str)
\"\"\"
function $(process.id)$(process.id in keywords ? "_" : "")($args_str)
ProcessNode("$(process.id)", Dict{Symbol, Any}(($args_dict_str)))
end
"""

if Meta.parse(code).head != :incomplete
append!(processes_codes, [code])
else
println(code)
end

catch e
append!(warnings, [(process.id => e)])
end
end
code = join(processes_codes, "\n")
length(warnings) > 0 && @warn join(vcat(["Ignore processes with errors"], warnings), "\n")
return code
end

0 comments on commit 46d7dde

Please sign in to comment.