-
Notifications
You must be signed in to change notification settings - Fork 0
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
jidea-56 Metadata endpoint #5
Conversation
system_file <- function(...) { | ||
tryCatch({ | ||
system.file(..., mustWork = TRUE, package = "daedalus.api") | ||
}, error = function(e) { | ||
stop(sprintf("Failed to locate file from args\n%s", | ||
paste(list(...), collapse = " "))) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handy method stolen from hintr!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 comment and 1 question. Looks good as far as I can tell without my glaR
ses on!
"defaultOption": "none", | ||
"ordered": true, | ||
"options": [ | ||
{ "id": "none", "label": "None" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a question than a comment, but it's possible in the future we'll need to annotate each such option with a description to explain what precisely is meant by e.g. 'Medium'. I presume it's OK to cross that bridge when we get to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we can add a "description" field if required.
R/parameters.R
Outdated
# Allowed parameter ids which we can pass to the model | ||
expected_parameters <- c( | ||
"country", | ||
"pathogen", | ||
"response", | ||
"vaccine" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a bit misleading to store data that is used only by a test, outside of the tests folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, true - but I think we might expand on and make further user of this. For example, we might want to validate the parameters in run requests... (although maybe we just let the package do that?) Happy to move it into tests for now though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll let @pratikunterwegs opine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could live in tests for now and move to internal package data once the need becomes clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @EmmaLRussell, looks good to me and I was able to follow the Readme instructions to pull and run the container. Just a few small suggestions here and there.
R/util.R
Outdated
read_json <- function(filename) { | ||
json <- jsonlite::fromJSON(system_file("json", filename)) | ||
json | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be replaced by the {jsonlite} function of the same name, with simplifyVector = TRUE
? Or alternatively, using jsonlite::fromJSON()
directly? The wrapper being the same name as the {jsonlite} had me confused what it was doing (especially as the behaviour, e.g. simplifyVector
is the opposite of what the {jsonlite} version does).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point. How about if I change the name to something not shared with jsonlite to make it clear this is a special for the API? read_local_json_file
? I'm just thinking that neither fromJSON
nor read_json
are going to do exactly the same as their jsonlite equivalent since it's selecting the folder to read from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
read_local_json()
sounds good!
system_file <- function(...) { | ||
tryCatch({ | ||
system.file(..., mustWork = TRUE, package = "daedalus.api") | ||
}, error = function(e) { | ||
stop(sprintf("Failed to locate file from args\n%s", | ||
paste(list(...), collapse = " "))) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see why this function has been included, although it's over-writing a well known base function; the informative error is useful. Could we get a small comment explaining that?
R/api.R
Outdated
# JIDEA-62: we will read in correct metadata version according to | ||
# model_version | ||
metadata_file <- sprintf("metadata_%s.json", model_version) | ||
response <- read_json(metadata_file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was initially confused as to where this function was coming from, but now I see it's redefined in this package; I've added a suggestion to switch to jsonlite::fromJSON()
instead
R/api.R
Outdated
metadata <- function() { | ||
# JIDEA-62: we will use relevant model version - from qs if specified, else | ||
# from latest available metadata file | ||
model_version <- scalar("0.1.0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this pull from the package version for now? The model structure and data versions are all bundled together in the package version at the moment anyway.
tests/testthat/test-endpoints.R
Outdated
|
||
test_that("Can get metadata", { | ||
endpoint <- daedalus_api_endpoint("GET", "/metadata") | ||
res <- endpoint$run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could I suggest a no conditions expectation here:
res <- endpoint$run() | |
expect_no_condition( | |
res <- endpoint$run() | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, and I've put it on the root call too..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha, that upsets the linter though: Avoid implicit assignments in function calls.
So have excluded those lines from linting!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, a classic. The other linter complaints can usually be fixed with a styler::style_pkg()
call
tests/testthat/test-endpoints.R
Outdated
lapply(res$data$parameters$id, function(id) { | ||
expect_true(id %in% expected_parameters) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be simplified to an expect_identical()
; if that proves too strict later it can always be changed to expect_setequal()
or similar.
lapply(res$data$parameters$id, function(id) { | |
expect_true(id %in% expected_parameters) | |
}) | |
expect_identical( | |
res$data$parameters$id, | |
expected_parameters | |
) |
tests/testthat/test-endpoints.R
Outdated
lapply(seq_along(country_options), function(idx) { | ||
daedalus_country <- scalar(daedalus_countries[[idx]]) | ||
expect_identical(country_options[[idx]]$id, daedalus_country) | ||
expect_identical(country_options[[idx]]$label, daedalus_country) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could I suggest sort of transposing this chunk so the outermost function always returns the expectations - no sweat really as this does what's needed. If you keep the original version, I don't think the scalar()
call on daedalus_countries
is needed.
lapply(seq_along(country_options), function(idx) { | |
daedalus_country <- scalar(daedalus_countries[[idx]]) | |
expect_identical(country_options[[idx]]$id, daedalus_country) | |
expect_identical(country_options[[idx]]$label, daedalus_country) | |
}) | |
expect_identical( | |
vapply(country_options, `[[`, FUN.VALUE = character(1), "id"), | |
daedalus_countries | |
) | |
expect_identical( | |
vapply(country_options, `[[`, FUN.VALUE = character(1), "label"), | |
daedalus_countries | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've gone for a version of this approach, but with syntax that I find easier to cope with! (more verbose though..)
# expect country ids to match those from daedalus
expect_identical(
vapply(country_options, function(option) {
option$id
}, character(1L)),
daedalus_countries
)
# expect country labels to match those from daedalus
expect_identical(
vapply(country_options, function(option) {
option$label
}, character(1L)),
daedalus_countries
)
Thank you, it’s awesome to have this in place! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @EmmaLRussell looks good!
Thanks both! |
This branch adds the first cut of a metadata endpoint to allow the web app to get going with parameters metadata.
I was getting a bit bogged down with attempting to implement the versioning part of this, so have spun that out into a separate ticket (jidea-62) - but I've included a description of the intended approach in the README here. For now, we always read in a hardcoded metadata version (0.1.0), and this version is also returned in the response.
This branch implements:
/metadata
endpoint which:I am very bad at R - please let me know anything that could have been done more sensibly in a different way!
To see the endpoint in action:
then
docker kill dapi
to tear down