diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c774e4a..d864e65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,17 +21,12 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20 - - name: Install Redocly - run: npm install -g @redocly/cli@latest - name: Lint OpenAPI with Redocly - run: redocly lint openapi.yaml - - - name: Install spectral - run: npm install -g @stoplight/spectral-cli + run: npx --package @redocly/cli@latest redocly lint openapi.yaml - name: Lint OpenAPI with Spectral - run: spectral lint openapi.yaml + run: npx --package @stoplight/spectral-cli spectral lint openapi.yaml - name: Setup Python uses: actions/setup-python@v5 diff --git a/.gitignore b/.gitignore index 73cf7b8..5079cc5 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,7 @@ __pycache__ /venv python/.venv/ python/heat.toml -RemoteBMI.jl/example/Project.toml \ No newline at end of file +RemoteBMI.jl/example/Project.toml +RemoteBMI.jl/example/heat.toml +openapi-generator-cli.jar +openapitools.json \ No newline at end of file diff --git a/RemoteBMI.jl/README.md b/RemoteBMI.jl/README.md index f3c26db..760c39e 100644 --- a/RemoteBMI.jl/README.md +++ b/RemoteBMI.jl/README.md @@ -35,6 +35,7 @@ BestieTemplate.generate("RemoteBMI.jl") The openapi server stubs where generated using the following command: ```shell -npx @openapitools/openapi-generator-cli generate -i ./openapi.yaml -g julia-server -o julia-server --additional-properties=packageName=BmiServer --additional-properties=exportModels=true +wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.8.0/openapi-generator-cli-7.8.0.jar -O openapi-generator-cli.jar +java -jar ./openapi-generator-cli.jar generate -i ./openapi.yaml -g julia-server -o julia-server --additional-properties=packageName=BmiServer --additional-properties=exportModels=true # Copy the generated files to RemoteBMI.jl/src/ ``` \ No newline at end of file diff --git a/RemoteBMI.jl/example/README.md b/RemoteBMI.jl/example/README.md index ae6df17..f279f53 100644 --- a/RemoteBMI.jl/example/README.md +++ b/RemoteBMI.jl/example/README.md @@ -10,7 +10,7 @@ add https://github.com/csdms/bmi-example-julia#b5d963e6bf864f5d42769e6cc0814dd7b dev .. CTRL-D # Run server -export BMI_SERVER_PORT=50555 +export BMI_PORT=50555 julia --project=$PWD heat_bmi_server.jl ``` @@ -24,16 +24,27 @@ Interact with it using the Python client. ```python from remotebmi.client.client import RemoteBmiClient -from remotebmi.client.reserve import reserve_values +from remotebmi.reserve import reserve_values client = RemoteBmiClient('http://localhost:50555') # TODO use placeholder for path # client.initialize('/heat.toml') client.initialize('/home/stefanv/git/eWaterCycle/remotebmi/python/heat.toml') -# TODO Julia server throws error here client.get_component_name() +'The 2D Heat Equation' client.update() client.get_current_time() +0.25 +client.get_time_units() +'s' +client.get_var_location('plate_surface__temperature') +'node' +client.get_var_type('plate_surface__temperature') +numpy.float64 +client.get_var_grid('plate_surface__temperature') +0 +client.get_grid_type(0) +'uniform_rectilinear' dest = reserve_values(client, 'plate_surface__temperature') r = client.get_value('plate_surface__temperature', dest) r diff --git a/RemoteBMI.jl/src/BmiServer.jl b/RemoteBMI.jl/src/BmiServer.jl index cdd310e..323d02d 100644 --- a/RemoteBMI.jl/src/BmiServer.jl +++ b/RemoteBMI.jl/src/BmiServer.jl @@ -9,7 +9,7 @@ The following server methods must be implemented: - **get_component_name** - *invocation:* GET /get_component_name - - *signature:* get_component_name(req::HTTP.Request;) -> String + - *signature:* get_component_name(req::HTTP.Request;) -> GetComponentNameResponse - **get_input_item_count** - *invocation:* GET /get_input_item_count - *signature:* get_input_item_count(req::HTTP.Request;) -> Int64 @@ -36,13 +36,13 @@ The following server methods must be implemented: - *signature:* get_grid_size(req::HTTP.Request, grid::Int64;) -> Int64 - **get_grid_type** - *invocation:* GET /get_grid_type/{grid} - - *signature:* get_grid_type(req::HTTP.Request, grid::Int64;) -> BmiGetGridTypeResponse + - *signature:* get_grid_type(req::HTTP.Request, grid::Int64;) -> GetGridTypeResponse - **finalize** - *invocation:* DELETE /finalize - *signature:* finalize(req::HTTP.Request;) -> Nothing - **initialize** - *invocation:* POST /initialize - - *signature:* initialize(req::HTTP.Request, bmi_initialize_request::BmiInitializeRequest;) -> Nothing + - *signature:* initialize(req::HTTP.Request, initialize_request::InitializeRequest;) -> Nothing - **update** - *invocation:* POST /update - *signature:* update(req::HTTP.Request;) -> Nothing @@ -63,7 +63,7 @@ The following server methods must be implemented: - *signature:* set_value(req::HTTP.Request, name::String, request_body::Vector{Float64};) -> Nothing - **set_value_at_indices** - *invocation:* POST /set_value_at_indices/{name} - - *signature:* set_value_at_indices(req::HTTP.Request, name::String, bmi_set_value_at_indices_request::BmiSetValueAtIndicesRequest;) -> Nothing + - *signature:* set_value_at_indices(req::HTTP.Request, name::String, set_value_at_indices_request::SetValueAtIndicesRequest;) -> Nothing - **get_current_time** - *invocation:* GET /get_current_time - *signature:* get_current_time(req::HTTP.Request;) -> Float64 @@ -78,7 +78,7 @@ The following server methods must be implemented: - *signature:* get_time_step(req::HTTP.Request;) -> Float64 - **get_time_units** - *invocation:* GET /get_time_units - - *signature:* get_time_units(req::HTTP.Request;) -> String + - *signature:* get_time_units(req::HTTP.Request;) -> GetTimeUnitsResponse - **get_grid_origin** - *invocation:* GET /get_grid_origin/{grid} - *signature:* get_grid_origin(req::HTTP.Request, grid::Int64;) -> Vector{Float64} @@ -123,10 +123,10 @@ The following server methods must be implemented: - *signature:* get_var_nbytes(req::HTTP.Request, name::String;) -> Int64 - **get_var_type** - *invocation:* GET /get_var_type/{name} - - *signature:* get_var_type(req::HTTP.Request, name::String;) -> String + - *signature:* get_var_type(req::HTTP.Request, name::String;) -> GetVarTypeResponse - **get_var_units** - *invocation:* GET /get_var_units/{name} - - *signature:* get_var_units(req::HTTP.Request, name::String;) -> String + - *signature:* get_var_units(req::HTTP.Request, name::String;) -> GetVarUnitsResponse """ module BmiServer @@ -187,10 +187,14 @@ function register(router::HTTP.Router, impl; path_prefix::String="", optional_mi end # export models -export BmiGetGridTypeResponse -export BmiInitializeRequest -export BmiSetValueAtIndicesRequest +export GetComponentNameResponse +export GetGridTypeResponse +export GetTimeUnitsResponse export GetVarLocationResponseLocation +export GetVarTypeResponse +export GetVarUnitsResponse +export InitializeRequest export ProblemDetails +export SetValueAtIndicesRequest end # module BmiServer diff --git a/RemoteBMI.jl/src/RemoteBMI.jl b/RemoteBMI.jl/src/RemoteBMI.jl index ce4be37..63dd8e4 100644 --- a/RemoteBMI.jl/src/RemoteBMI.jl +++ b/RemoteBMI.jl/src/RemoteBMI.jl @@ -9,14 +9,14 @@ import BasicModelInterface as BMI # TODO move route implementations to own module -function initialize(req::HTTP.Request, bmi_initialize_request::BmiInitializeRequest)::Nothing +function initialize(req::HTTP.Request, initialize_request::InitializeRequest)::Nothing global m - m = BMI.initialize(MyModel, bmi_initialize_request.config_file) + m = BMI.initialize(MyModel, initialize_request.config_file) return nothing end -function get_component_name(req::HTTP.Request;)::String - return BMI.get_component_name(m) +function get_component_name(req::HTTP.Request)::GetComponentNameResponse + return GetComponentNameResponse(BMI.get_component_name(m)) end function get_input_item_count(req::HTTP.Request;)::Int64 @@ -89,8 +89,8 @@ function get_grid_size(req::HTTP.Request, grid::Int64;)::Int64 return BMI.get_grid_size(m, grid) end -function get_grid_type(req::HTTP.Request, grid::Int64;)::BmiGetGridTypeResponse - return BMI.get_grid_type(m, grid) +function get_grid_type(req::HTTP.Request, grid::Int64;)::GetGridTypeResponse + return GetGridTypeResponse(type=BMI.get_grid_type(m, grid)) end function finalize(req::HTTP.Request;)::Nothing @@ -119,6 +119,7 @@ function reserve_grid_coords(m, grid::Int64, dim_index::Int8)::Vector{Float64} size = BMI.get_grid_node_count(m, grid) else error("Unsupported grid type: $mtype") + end return zeros(Float64, size) end @@ -141,8 +142,8 @@ function set_value(req::HTTP.Request, name::String, request_body::Vector{Float64 BMI.set_value(m, name, request_body) end -function set_value_at_indices(req::HTTP.Request, name::String, bmi_set_value_at_indices_request::BmiSetValueAtIndicesRequest;)::Nothing - BMI.set_value_at_indices(m, name, bmi_set_value_at_indices_request) +function set_value_at_indices(req::HTTP.Request, name::String, set_value_at_indices_request::SetValueAtIndicesRequest;)::Nothing + BMI.set_value_at_indices(m, name, set_value_at_indices_request) end function get_current_time(req::HTTP.Request;)::Float64 @@ -150,6 +151,8 @@ function get_current_time(req::HTTP.Request;)::Float64 end function get_end_time(req::HTTP.Request;)::Float64 + # Julia Heat model returns Inf, but that is not a valid JSON number. + # Therefore, it gets converted to null in the JSON response. return BMI.get_end_time(m) end @@ -161,8 +164,8 @@ function get_time_step(req::HTTP.Request;)::Float64 return BMI.get_time_step(m) end -function get_time_units(req::HTTP.Request;)::String - return BMI.get_time_units(m) +function get_time_units(req::HTTP.Request;)::GetTimeUnitsResponse + return GetTimeUnitsResponse(BMI.get_time_units(m)) end function get_grid_origin(req::HTTP.Request, grid::Int64;)::Vector{Float64} @@ -247,17 +250,17 @@ function get_var_itemsize(req::HTTP.Request, name::String;)::Int64 end function get_var_location(req::HTTP.Request, name::String;)::GetVarLocationResponseLocation - return BMI.get_var_location(m, name) + return GetVarLocationResponseLocation(BMI.get_var_location(m, name)) end function get_var_nbytes(req::HTTP.Request, name::String;)::Int64 return BMI.get_var_nbytes(m, name) end -function get_var_type(req::HTTP.Request, name::String;)::String +function get_var_type(req::HTTP.Request, name::String;)::GetVarTypeResponse raw_type = BMI.get_var_type(m, name) map = Dict( - "Float64" => "float64", + "Float64" => "double", "Float32" => "float32", "Int64" => "int64", "Int32" => "int32", @@ -267,11 +270,11 @@ function get_var_type(req::HTTP.Request, name::String;)::String if type == Any error("Invalid data type returned by model: $raw_type, allowed types are: Float64, Float32, Int64, Int32") end - return type + return GetVarTypeResponse(type) end -function get_var_units(req::HTTP.Request, name::String;)::String - return BMI.get_var_units(m, name) +function get_var_units(req::HTTP.Request, name::String;)::GetVarUnitsResponse + return GetVarUnitsResponse(BMI.get_var_units(m, name)) end function run(model, host, port) diff --git a/RemoteBMI.jl/src/apis/api_GettersApi.jl b/RemoteBMI.jl/src/apis/api_GettersApi.jl index dc407a6..d6ba826 100644 --- a/RemoteBMI.jl/src/apis/api_GettersApi.jl +++ b/RemoteBMI.jl/src/apis/api_GettersApi.jl @@ -17,6 +17,8 @@ function get_value_validate(handler) function get_value_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_value", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -46,6 +48,8 @@ function get_value_at_indices_validate(handler) function get_value_at_indices_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_value_at_indices", :minLength, openapi_params["name"], 1) + return handler(req) end end diff --git a/RemoteBMI.jl/src/apis/api_IRFApi.jl b/RemoteBMI.jl/src/apis/api_IRFApi.jl index a8b73a5..b2ad21e 100644 --- a/RemoteBMI.jl/src/apis/api_IRFApi.jl +++ b/RemoteBMI.jl/src/apis/api_IRFApi.jl @@ -31,7 +31,7 @@ end function initialize_read(handler) function initialize_read_handler(req::HTTP.Request) openapi_params = Dict{String,Any}() - openapi_params["BmiInitializeRequest"] = OpenAPI.Servers.to_param_type(BmiInitializeRequest, String(req.body)) + openapi_params["InitializeRequest"] = OpenAPI.Servers.to_param_type(InitializeRequest, String(req.body)) req.context[:openapi_params] = openapi_params return handler(req) @@ -49,7 +49,7 @@ end function initialize_invoke(impl; post_invoke=nothing) function initialize_invoke_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] - ret = impl.initialize(req::HTTP.Request, openapi_params["BmiInitializeRequest"];) + ret = impl.initialize(req::HTTP.Request, openapi_params["InitializeRequest"];) resp = OpenAPI.Servers.server_response(ret) return (post_invoke === nothing) ? resp : post_invoke(req, resp) end diff --git a/RemoteBMI.jl/src/apis/api_SettersApi.jl b/RemoteBMI.jl/src/apis/api_SettersApi.jl index 8931308..33de8ac 100644 --- a/RemoteBMI.jl/src/apis/api_SettersApi.jl +++ b/RemoteBMI.jl/src/apis/api_SettersApi.jl @@ -18,6 +18,8 @@ function set_value_validate(handler) function set_value_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "set_value", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -36,7 +38,7 @@ function set_value_at_indices_read(handler) openapi_params = Dict{String,Any}() path_params = HTTP.getparams(req) openapi_params["name"] = OpenAPI.Servers.to_param(String, path_params, "name", required=true, ) - openapi_params["BmiSetValueAtIndicesRequest"] = OpenAPI.Servers.to_param_type(BmiSetValueAtIndicesRequest, String(req.body)) + openapi_params["SetValueAtIndicesRequest"] = OpenAPI.Servers.to_param_type(SetValueAtIndicesRequest, String(req.body)) req.context[:openapi_params] = openapi_params return handler(req) @@ -47,6 +49,8 @@ function set_value_at_indices_validate(handler) function set_value_at_indices_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "set_value_at_indices", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -54,7 +58,7 @@ end function set_value_at_indices_invoke(impl; post_invoke=nothing) function set_value_at_indices_invoke_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] - ret = impl.set_value_at_indices(req::HTTP.Request, openapi_params["name"], openapi_params["BmiSetValueAtIndicesRequest"];) + ret = impl.set_value_at_indices(req::HTTP.Request, openapi_params["name"], openapi_params["SetValueAtIndicesRequest"];) resp = OpenAPI.Servers.server_response(ret) return (post_invoke === nothing) ? resp : post_invoke(req, resp) end diff --git a/RemoteBMI.jl/src/apis/api_VariableInformationApi.jl b/RemoteBMI.jl/src/apis/api_VariableInformationApi.jl index c1f6856..9ac76f8 100644 --- a/RemoteBMI.jl/src/apis/api_VariableInformationApi.jl +++ b/RemoteBMI.jl/src/apis/api_VariableInformationApi.jl @@ -17,6 +17,8 @@ function get_var_grid_validate(handler) function get_var_grid_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_grid", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -45,6 +47,8 @@ function get_var_itemsize_validate(handler) function get_var_itemsize_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_itemsize", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -73,6 +77,8 @@ function get_var_location_validate(handler) function get_var_location_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_location", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -101,6 +107,8 @@ function get_var_nbytes_validate(handler) function get_var_nbytes_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_nbytes", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -129,6 +137,8 @@ function get_var_type_validate(handler) function get_var_type_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_type", :minLength, openapi_params["name"], 1) + return handler(req) end end @@ -157,6 +167,8 @@ function get_var_units_validate(handler) function get_var_units_validate_handler(req::HTTP.Request) openapi_params = req.context[:openapi_params] + OpenAPI.validate_param("name", "get_var_units", :minLength, openapi_params["name"], 1) + return handler(req) end end diff --git a/RemoteBMI.jl/src/modelincludes.jl b/RemoteBMI.jl/src/modelincludes.jl index a5ceaec..8afe3c1 100644 --- a/RemoteBMI.jl/src/modelincludes.jl +++ b/RemoteBMI.jl/src/modelincludes.jl @@ -1,8 +1,12 @@ # This file was generated by the Julia OpenAPI Code Generator # Do not modify this file directly. Modify the OpenAPI specification instead. -include("models/model_BmiGetGridTypeResponse.jl") -include("models/model_BmiInitializeRequest.jl") -include("models/model_BmiSetValueAtIndicesRequest.jl") +include("models/model_GetComponentNameResponse.jl") +include("models/model_GetGridTypeResponse.jl") +include("models/model_GetTimeUnitsResponse.jl") include("models/model_GetVarLocationResponseLocation.jl") +include("models/model_GetVarTypeResponse.jl") +include("models/model_GetVarUnitsResponse.jl") +include("models/model_InitializeRequest.jl") include("models/model_ProblemDetails.jl") +include("models/model_SetValueAtIndicesRequest.jl") diff --git a/RemoteBMI.jl/src/models/model_GetComponentNameResponse.jl b/RemoteBMI.jl/src/models/model_GetComponentNameResponse.jl new file mode 100644 index 0000000..c0e860e --- /dev/null +++ b/RemoteBMI.jl/src/models/model_GetComponentNameResponse.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""GetComponentNameResponse + + GetComponentNameResponse(; + name=nothing, + ) + + - name::String +""" +Base.@kwdef mutable struct GetComponentNameResponse <: OpenAPI.APIModel + name::Union{Nothing, String} = nothing + + function GetComponentNameResponse(name, ) + OpenAPI.validate_property(GetComponentNameResponse, Symbol("name"), name) + return new(name, ) + end +end # type GetComponentNameResponse + +const _property_types_GetComponentNameResponse = Dict{Symbol,String}(Symbol("name")=>"String", ) +OpenAPI.property_type(::Type{ GetComponentNameResponse }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetComponentNameResponse[name]))} + +function check_required(o::GetComponentNameResponse) + o.name === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetComponentNameResponse }, name::Symbol, val) + if name === Symbol("name") + OpenAPI.validate_param(name, "GetComponentNameResponse", :minLength, val, 1) + end +end diff --git a/RemoteBMI.jl/src/models/model_GetGridTypeResponse.jl b/RemoteBMI.jl/src/models/model_GetGridTypeResponse.jl new file mode 100644 index 0000000..5492e22 --- /dev/null +++ b/RemoteBMI.jl/src/models/model_GetGridTypeResponse.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""GetGridTypeResponse + + GetGridTypeResponse(; + type=nothing, + ) + + - type::String +""" +Base.@kwdef mutable struct GetGridTypeResponse <: OpenAPI.APIModel + type::Union{Nothing, String} = nothing + + function GetGridTypeResponse(type, ) + OpenAPI.validate_property(GetGridTypeResponse, Symbol("type"), type) + return new(type, ) + end +end # type GetGridTypeResponse + +const _property_types_GetGridTypeResponse = Dict{Symbol,String}(Symbol("type")=>"String", ) +OpenAPI.property_type(::Type{ GetGridTypeResponse }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetGridTypeResponse[name]))} + +function check_required(o::GetGridTypeResponse) + o.type === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetGridTypeResponse }, name::Symbol, val) + if name === Symbol("type") + OpenAPI.validate_param(name, "GetGridTypeResponse", :enum, val, ["scalar", "points", "vector", "unstructured", "structured_quadrilateral", "rectilinear", "uniform_rectilinear"]) + end +end diff --git a/RemoteBMI.jl/src/models/model_GetTimeUnitsResponse.jl b/RemoteBMI.jl/src/models/model_GetTimeUnitsResponse.jl new file mode 100644 index 0000000..5ba33a8 --- /dev/null +++ b/RemoteBMI.jl/src/models/model_GetTimeUnitsResponse.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""GetTimeUnitsResponse + + GetTimeUnitsResponse(; + units=nothing, + ) + + - units::String +""" +Base.@kwdef mutable struct GetTimeUnitsResponse <: OpenAPI.APIModel + units::Union{Nothing, String} = nothing + + function GetTimeUnitsResponse(units, ) + OpenAPI.validate_property(GetTimeUnitsResponse, Symbol("units"), units) + return new(units, ) + end +end # type GetTimeUnitsResponse + +const _property_types_GetTimeUnitsResponse = Dict{Symbol,String}(Symbol("units")=>"String", ) +OpenAPI.property_type(::Type{ GetTimeUnitsResponse }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetTimeUnitsResponse[name]))} + +function check_required(o::GetTimeUnitsResponse) + o.units === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetTimeUnitsResponse }, name::Symbol, val) + if name === Symbol("units") + OpenAPI.validate_param(name, "GetTimeUnitsResponse", :minLength, val, 1) + end +end diff --git a/RemoteBMI.jl/src/models/model_GetVarLocationResponseLocation.jl b/RemoteBMI.jl/src/models/model_GetVarLocationResponseLocation.jl index 4aec63b..afe49be 100644 --- a/RemoteBMI.jl/src/models/model_GetVarLocationResponseLocation.jl +++ b/RemoteBMI.jl/src/models/model_GetVarLocationResponseLocation.jl @@ -2,8 +2,33 @@ # Do not modify this file directly. Modify the OpenAPI specification instead. -if !isdefined(@__MODULE__, :GetVarLocationResponseLocation) - const GetVarLocationResponseLocation = String -else - @warn("Skipping redefinition of GetVarLocationResponseLocation to String") +@doc raw"""GetVarLocationResponseLocation + + GetVarLocationResponseLocation(; + location="node", + ) + + - location::String +""" +Base.@kwdef mutable struct GetVarLocationResponseLocation <: OpenAPI.APIModel + location::Union{Nothing, String} = "node" + + function GetVarLocationResponseLocation(location, ) + OpenAPI.validate_property(GetVarLocationResponseLocation, Symbol("location"), location) + return new(location, ) + end +end # type GetVarLocationResponseLocation + +const _property_types_GetVarLocationResponseLocation = Dict{Symbol,String}(Symbol("location")=>"String", ) +OpenAPI.property_type(::Type{ GetVarLocationResponseLocation }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetVarLocationResponseLocation[name]))} + +function check_required(o::GetVarLocationResponseLocation) + o.location === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetVarLocationResponseLocation }, name::Symbol, val) + if name === Symbol("location") + OpenAPI.validate_param(name, "GetVarLocationResponseLocation", :enum, val, ["node", "edge", "face"]) + end end diff --git a/RemoteBMI.jl/src/models/model_GetVarTypeResponse.jl b/RemoteBMI.jl/src/models/model_GetVarTypeResponse.jl new file mode 100644 index 0000000..dedee32 --- /dev/null +++ b/RemoteBMI.jl/src/models/model_GetVarTypeResponse.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""GetVarTypeResponse + + GetVarTypeResponse(; + type=nothing, + ) + + - type::String +""" +Base.@kwdef mutable struct GetVarTypeResponse <: OpenAPI.APIModel + type::Union{Nothing, String} = nothing + + function GetVarTypeResponse(type, ) + OpenAPI.validate_property(GetVarTypeResponse, Symbol("type"), type) + return new(type, ) + end +end # type GetVarTypeResponse + +const _property_types_GetVarTypeResponse = Dict{Symbol,String}(Symbol("type")=>"String", ) +OpenAPI.property_type(::Type{ GetVarTypeResponse }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetVarTypeResponse[name]))} + +function check_required(o::GetVarTypeResponse) + o.type === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetVarTypeResponse }, name::Symbol, val) + if name === Symbol("type") + OpenAPI.validate_param(name, "GetVarTypeResponse", :enum, val, ["float", "double", "int32", "int64"]) + end +end diff --git a/RemoteBMI.jl/src/models/model_GetVarUnitsResponse.jl b/RemoteBMI.jl/src/models/model_GetVarUnitsResponse.jl new file mode 100644 index 0000000..5bc0637 --- /dev/null +++ b/RemoteBMI.jl/src/models/model_GetVarUnitsResponse.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""GetVarUnitsResponse + + GetVarUnitsResponse(; + units=nothing, + ) + + - units::String +""" +Base.@kwdef mutable struct GetVarUnitsResponse <: OpenAPI.APIModel + units::Union{Nothing, String} = nothing + + function GetVarUnitsResponse(units, ) + OpenAPI.validate_property(GetVarUnitsResponse, Symbol("units"), units) + return new(units, ) + end +end # type GetVarUnitsResponse + +const _property_types_GetVarUnitsResponse = Dict{Symbol,String}(Symbol("units")=>"String", ) +OpenAPI.property_type(::Type{ GetVarUnitsResponse }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_GetVarUnitsResponse[name]))} + +function check_required(o::GetVarUnitsResponse) + o.units === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ GetVarUnitsResponse }, name::Symbol, val) + if name === Symbol("units") + OpenAPI.validate_param(name, "GetVarUnitsResponse", :minLength, val, 1) + end +end diff --git a/RemoteBMI.jl/src/models/model_InitializeRequest.jl b/RemoteBMI.jl/src/models/model_InitializeRequest.jl new file mode 100644 index 0000000..47f1246 --- /dev/null +++ b/RemoteBMI.jl/src/models/model_InitializeRequest.jl @@ -0,0 +1,34 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""InitializeRequest + + InitializeRequest(; + config_file=nothing, + ) + + - config_file::String : Path to the configuration file. Should resolvable by web service. +""" +Base.@kwdef mutable struct InitializeRequest <: OpenAPI.APIModel + config_file::Union{Nothing, String} = nothing + + function InitializeRequest(config_file, ) + OpenAPI.validate_property(InitializeRequest, Symbol("config_file"), config_file) + return new(config_file, ) + end +end # type InitializeRequest + +const _property_types_InitializeRequest = Dict{Symbol,String}(Symbol("config_file")=>"String", ) +OpenAPI.property_type(::Type{ InitializeRequest }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_InitializeRequest[name]))} + +function check_required(o::InitializeRequest) + o.config_file === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ InitializeRequest }, name::Symbol, val) + if name === Symbol("config_file") + OpenAPI.validate_param(name, "InitializeRequest", :minLength, val, 0) + end +end diff --git a/RemoteBMI.jl/src/models/model_ProblemDetails.jl b/RemoteBMI.jl/src/models/model_ProblemDetails.jl index 42c2d28..3aa9de7 100644 --- a/RemoteBMI.jl/src/models/model_ProblemDetails.jl +++ b/RemoteBMI.jl/src/models/model_ProblemDetails.jl @@ -3,6 +3,7 @@ @doc raw"""ProblemDetails +Definition from https://datatracker.ietf.org/doc/html/rfc9457#name-json-schema-for-http-proble ProblemDetails(; type=nothing, @@ -12,11 +13,11 @@ instance=nothing, ) - - type::String - - title::String - - status::Int64 - - detail::String - - instance::String + - type::String : A URI reference that identifies the problem type. + - title::String : A short, human-readable summary of the problem type. + - status::Int64 : The HTTP status code generated by the origin server for this occurrence of the problem. + - detail::String : A human-readable explanation specific to this occurrence of the problem. + - instance::String : A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. """ Base.@kwdef mutable struct ProblemDetails <: OpenAPI.APIModel type::Union{Nothing, String} = nothing @@ -43,4 +44,14 @@ function check_required(o::ProblemDetails) end function OpenAPI.validate_property(::Type{ ProblemDetails }, name::Symbol, val) + if name === Symbol("type") + OpenAPI.validate_param(name, "ProblemDetails", :format, val, "uri-reference") + end + if name === Symbol("status") + OpenAPI.validate_param(name, "ProblemDetails", :maximum, val, 599, false) + OpenAPI.validate_param(name, "ProblemDetails", :minimum, val, 100, false) + end + if name === Symbol("instance") + OpenAPI.validate_param(name, "ProblemDetails", :format, val, "uri-reference") + end end diff --git a/RemoteBMI.jl/src/models/model_SetValueAtIndicesRequest.jl b/RemoteBMI.jl/src/models/model_SetValueAtIndicesRequest.jl new file mode 100644 index 0000000..5ec5ffe --- /dev/null +++ b/RemoteBMI.jl/src/models/model_SetValueAtIndicesRequest.jl @@ -0,0 +1,36 @@ +# This file was generated by the Julia OpenAPI Code Generator +# Do not modify this file directly. Modify the OpenAPI specification instead. + + +@doc raw"""SetValueAtIndicesRequest + + SetValueAtIndicesRequest(; + indices=nothing, + values=nothing, + ) + + - indices::Vector{Int64} + - values::Vector{Float64} +""" +Base.@kwdef mutable struct SetValueAtIndicesRequest <: OpenAPI.APIModel + indices::Union{Nothing, Vector{Int64}} = nothing + values::Union{Nothing, Vector{Float64}} = nothing + + function SetValueAtIndicesRequest(indices, values, ) + OpenAPI.validate_property(SetValueAtIndicesRequest, Symbol("indices"), indices) + OpenAPI.validate_property(SetValueAtIndicesRequest, Symbol("values"), values) + return new(indices, values, ) + end +end # type SetValueAtIndicesRequest + +const _property_types_SetValueAtIndicesRequest = Dict{Symbol,String}(Symbol("indices")=>"Vector{Int64}", Symbol("values")=>"Vector{Float64}", ) +OpenAPI.property_type(::Type{ SetValueAtIndicesRequest }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_SetValueAtIndicesRequest[name]))} + +function check_required(o::SetValueAtIndicesRequest) + o.indices === nothing && (return false) + o.values === nothing && (return false) + true +end + +function OpenAPI.validate_property(::Type{ SetValueAtIndicesRequest }, name::Symbol, val) +end diff --git a/openapi.yaml b/openapi.yaml index c586b5a..455c63a 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -522,9 +522,11 @@ paths: $ref: "#/components/schemas/GetTimeUnitsResponse" examples: hourly: - value: h + value: + units: h dayssince: - value: days since 2000-01-01 + value: + units: days since 2000-01-01 default: description: An unexpected error response. content: @@ -1104,15 +1106,27 @@ paths: components: schemas: GetVarLocationResponseLocation: - type: string - enum: - - node - - edge - - face - default: node + type: object + properties: + location: + type: string + enum: + - node + - edge + - face + default: node + additionalProperties: false + required: + - location GetComponentNameResponse: - type: string - minLength: 1 + type: object + properties: + name: + type: string + minLength: 1 + required: + - name + additionalProperties: false Count: type: integer format: int32 @@ -1136,15 +1150,21 @@ components: type: integer format: int64 GetGridTypeResponse: - type: string - enum: - - scalar - - points - - vector - - unstructured - - structured_quadrilateral - - rectilinear - - uniform_rectilinear + type: object + properties: + type: + type: string + enum: + - scalar + - points + - vector + - unstructured + - structured_quadrilateral + - rectilinear + - uniform_rectilinear + required: + - type + additionalProperties: false GetTimeResponse: type: number format: double @@ -1154,8 +1174,14 @@ components: format: double example: 1.0 GetTimeUnitsResponse: - type: string - minLength: 1 + type: object + properties: + units: + type: string + minLength: 1 + required: + - units + additionalProperties: false GetValueAtIndicesResponse: type: array items: @@ -1180,17 +1206,29 @@ components: type: string minLength: 1 GetVarTypeResponse: - type: string - externalDocs: - url: https://swagger.io/docs/specification/data-models/data-types/#numbers # yamllint disable-line rule:line-length - enum: - - float - - double - - int32 - - int64 + type: object + properties: + type: + type: string + externalDocs: + url: https://swagger.io/docs/specification/data-models/data-types/#numbers # yamllint disable-line rule:line-length + enum: + - float + - double + - int32 + - int64 + required: + - type + additionalProperties: false GetVarUnitsResponse: - type: string - minLength: 1 + type: object + properties: + units: + type: string + minLength: 1 + required: + - units + additionalProperties: false InitializeRequest: type: object properties: @@ -1201,6 +1239,7 @@ components: minLength: 0 required: - config_file + additionalProperties: false SetValueAtIndicesRequest: type: object properties: @@ -1218,6 +1257,7 @@ components: required: - indices - values + additionalProperties: false SetValueRequest: type: array items: diff --git a/python/remotebmi/client/client.py b/python/remotebmi/client/client.py index 9861435..738bb5c 100644 --- a/python/remotebmi/client/client.py +++ b/python/remotebmi/client/client.py @@ -30,7 +30,7 @@ def finalize(self): def get_component_name(self): response = self.client.get("/get_component_name") response.raise_for_status() - return response.json() + return response.json()["name"] def get_input_var_names(self): response = self.client.get("/get_input_var_names") @@ -60,7 +60,7 @@ def get_var_grid(self, name): def get_var_type(self, name): response = self.client.get(f"/get_var_type/{name}") response.raise_for_status() - raw_type = response.json() + raw_type = response.json()["type"] lookup = { "double": np.float64, "float": np.float32, @@ -72,7 +72,7 @@ def get_var_type(self, name): def get_var_units(self, name): response = self.client.get(f"/get_var_units/{name}") response.raise_for_status() - return response.json() + return response.json()["units"] def get_var_nbytes(self, name): response = self.client.get(f"/get_var_nbytes/{name}") @@ -82,7 +82,7 @@ def get_var_nbytes(self, name): def get_var_location(self, name): response = self.client.get(f"/get_var_location/{name}") response.raise_for_status() - return response.json() + return response.json()["location"] def get_var_itemsize(self, name): response = self.client.get(f"/get_var_itemsize/{name}") @@ -107,7 +107,7 @@ def get_end_time(self) -> float: def get_time_units(self) -> str: response = self.client.get("/get_time_units") response.raise_for_status() - return response.json() + return response.json()["units"] def get_time_step(self) -> float: response = self.client.get("/get_time_step") @@ -155,7 +155,7 @@ def get_grid_size(self, grid: int) -> int: def get_grid_type(self, grid: int) -> str: response = self.client.get(f"/get_grid_type/{grid}") response.raise_for_status() - return response.json() + return response.json()["type"] def get_grid_origin(self, grid: int, origin: ndarray) -> ndarray: response = self.client.get(f"/get_grid_origin/{grid}") diff --git a/python/remotebmi/server/api.py b/python/remotebmi/server/api.py index b992616..aa61e06 100644 --- a/python/remotebmi/server/api.py +++ b/python/remotebmi/server/api.py @@ -38,7 +38,7 @@ def finalize(): def get_component_name(): - return model().get_component_name() + return {"name": model().get_component_name()} def get_input_var_names(): @@ -62,11 +62,11 @@ def get_var_grid(name: str): def get_var_type(name: str): - return model().get_var_type(name) + return {"type": model().get_var_type(name) } def get_var_units(name: str): - return model().get_var_units(name) + return {"units": model().get_var_units(name)} def get_var_nbytes(name: str): @@ -74,7 +74,7 @@ def get_var_nbytes(name: str): def get_var_location(name: str): - return model().get_var_location(name) + return {"location": model().get_var_location(name)} def get_var_itemsize(name: str): @@ -85,6 +85,7 @@ def get_value(name: str): items = reserve_values(model(), name) return model().get_value(name, items) +# TODO correct typings def get_value_at_indices(name: str, indices: list): items = reserve_values_at_indices(model(), name, indices) @@ -106,7 +107,7 @@ def get_grid_rank(name: str): def get_grid_type(name: str): - return model().get_grid_type(name) + return {"type": model().get_grid_type(name)} def get_grid_shape(name: str): @@ -160,7 +161,7 @@ def get_time_step(): def get_time_units(): - return model().get_time_units() + return {"units": model().get_time_units()} def get_grid_edge_count(name: str): diff --git a/r-server/R/server.R b/r-server/R/server.R index ef91199..2b92634 100644 --- a/r-server/R/server.R +++ b/r-server/R/server.R @@ -10,7 +10,7 @@ get_component_name <- function(request, response, keys, ...) { response$status <- 200L response$type <- 'application/json' # TODO call model method - response$body <- "Some model name" + response$body <- list(name = "Some model name") response$format(json = format_json()) return(FALSE) }