Skip to content
This repository was archived by the owner on Oct 28, 2019. It is now read-only.

Commit d0ee0dd

Browse files
committed
Merge branch 'dev'
* dev: Bump version number to 0.2.12 Fail immediately in consume() if error code is 400. #57 Remove importFrom(utils, data) Remove vignette artefacts Rebuild vignettes Implement workarounds to pass R CMD check in wrapper.R Suppress warnings in download.datasets() to deal with some csv samples containing missing final line, i.e. missing line break. #115 Rebuild documentation using roxygen2 v5 Document how to use different regions. #105 Rename arguments from tries to .retry #116 Fixed typo in URL. #105 Update date Refactor, and catch error with NA values. #115
2 parents 2310f2c + fc0369b commit d0ee0dd

40 files changed

+308
-1392
lines changed

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Title: Interface with Azure Machine Learning Datasets, Experiments and Web Servi
44
Description: Functions and datasets to support Azure Machine Learning. This
55
allows you to interact with datasets, as well as publish and consume R functions
66
as API services.
7-
Version: 0.2.11
8-
Date: 2016-07-01
7+
Version: 0.2.12
8+
Date: 2016-07-13
99
Authors@R: c(
1010
person("Andrie", "de Vries", role=c("aut", "cre"), email="[email protected]"),
1111
person(family="Microsoft Corporation", role="cph"),

NAMESPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by roxygen2 (4.1.1): do not edit by hand
1+
# Generated by roxygen2: do not edit by hand
22

33
S3method(print,Datasets)
44
S3method(print,Experiments)

R/consume.R

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#' @export
3030
#'
3131
#' @inheritParams refresh
32+
#' @inheritParams publishWebService
3233
#' @param endpoint Either an AzureML web service endpoint returned by \code{\link{publishWebService}}, \code{\link{endpoints}}, or simply an AzureML web service from \code{\link{services}}; in the latter case the default endpoint for the service will be used.
3334
#' @param ... variable number of requests entered as lists in key-value format; optionally a single data frame argument.
3435
#' @param globalParam global parameters entered as a list, default value is an empty list
@@ -43,7 +44,7 @@
4344
#' @family consumption functions
4445
#' @importFrom jsonlite fromJSON
4546
#' @example inst/examples/example_publish.R
46-
consume <- function(endpoint, ..., globalParam, retryDelay = 10, output = "output1", tries = 5)
47+
consume <- function(endpoint, ..., globalParam, retryDelay = 10, output = "output1", .retry = 5)
4748
{
4849
if(is.Service(endpoint))
4950
{
@@ -73,7 +74,7 @@ consume <- function(endpoint, ..., globalParam, retryDelay = 10, output = "outpu
7374
}
7475
}
7576
# Make API call with parameters
76-
result <- callAPI(apiKey, requestUrl, requestsLists, globalParam, retryDelay, tries = tries)
77+
result <- callAPI(apiKey, requestUrl, requestsLists, globalParam, retryDelay, .retry = .retry)
7778
if(inherits(result, "error")) stop("AzureML returned an error code")
7879

7980
# Access output by converting from JSON into list and indexing into Results
@@ -104,14 +105,14 @@ consume <- function(endpoint, ..., globalParam, retryDelay = 10, output = "outpu
104105
# @param keyvalues the data to be passed to the web service
105106
# @param globalParam the global parameters for the web service
106107
# @param retryDelay number of seconds to wait after failing (max 3 tries) to try again
107-
# @param tries the number of retry attempts
108+
# @param .retry the number of retry attempts
108109
# @return result the response
109110
#
110111
# @importFrom jsonlite toJSON
111112
# @importFrom curl handle_setheaders new_handle handle_setopt curl_fetch_memory
112113
# @keywords internal
113114
callAPI <- function(apiKey, requestUrl, keyvalues, globalParam,
114-
retryDelay=10, tries = 5) {
115+
retryDelay=10, .retry = 5) {
115116
# Set number of tries and HTTP status to 0
116117
result <- NULL
117118
# Construct request payload
@@ -136,7 +137,7 @@ callAPI <- function(apiKey, requestUrl, keyvalues, globalParam,
136137
postfields = body
137138
)
138139
)
139-
r <- try_fetch(requestUrl, h, delay = retryDelay, tries = tries)
140+
r <- try_fetch(requestUrl, h, no_retry_on = 400, delay = retryDelay, .retry = .retry)
140141
result <- fromJSON(rawToChar(r$content))
141142
if(r$status_code >= 400) {
142143
stop(paste(capture.output(result), collapse="\n"))

R/datasets.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ delete.datasets <- function(ws, name, host){
268268
curl_escape(ws$id),
269269
curl_escape(familyId)
270270
)
271-
z <- try_fetch(uri, h, tries = 3, delay = 2)
271+
z <- try_fetch(uri, h, .retry = 3, delay = 2)
272272
z$status_code
273273
}
274274
status_code <- vapply(datasets$FamilyId, delete_one, FUN.VALUE = numeric(1), USE.NAMES = FALSE)

R/discover.R

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -86,43 +86,15 @@ discoverSchema <- function(helpURL, scheme = "https",
8686

8787
# Accesses the names of the columns in the example
8888
# and stores it in a list of column names
89-
# columnNames <- vector("list", length = length(inputExample))
90-
# columnNames <- list()
91-
# for(i in seq_along(inputExample)) {
92-
# columnNames[[i]] = names(inputExample)[i]
93-
# }
9489
columnNames <- lapply(seq_along(inputExample), function(i)names(inputExample[i]))
9590

96-
# Uses multiple nested loops to access the various paths in the
97-
# swagger document and find the execution path
98-
foundExecPath = FALSE
99-
pathNo = 0
100-
execPathNo = -1
101-
for(execPath in swagger$paths) {
102-
pathNo = pathNo + 1
103-
for(operationpath in execPath) {
104-
for(operation in operationpath) {
105-
# Goes through the characteristcs in every operation e.g. operationId
106-
for(charac in operation) {
107-
# Finds the path in which the
108-
# operationId (characteristic of the path) == execute
109-
# and sets the execution path number
110-
if(charac[1] == "execute")
111-
{
112-
#Sets found execution path to true
113-
foundExecPath = TRUE
114-
execPathNo = pathNo
115-
break
116-
}
117-
}
118-
}
119-
}
91+
execPathNo <- grep("/execute\\?", names(swagger$paths))
92+
if(is.numeric(execPathNo)) {
93+
executePath <- names(swagger$paths)[[execPathNo]]
94+
} else {
95+
"Path not found"
12096
}
12197

122-
# Stores the execution path
123-
executePath <- if(foundExecPath) names(swagger$paths)[[execPathNo]]
124-
else "Path not found"
125-
12698
# Constructs the request URL with the parameters as well as execution path found.
12799
# The separator is set to an empty string
128100
requestUrl <- paste0(scheme,"://", host,

R/fetch.R

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ validate_response <- function(r){
6767
# @param uri the uri to fetch
6868
# @param handle a curl handle
6969
# @param retry_on HTTP status codes that result in retry
70-
# @param tries number of tries before failing
70+
# @param .retry number of tries before failing
7171
# @param delay in seconds between retries, subject to exponent
7272
# @param exponent increment each successive delay by delay^exponent
7373
# @param no_message_threshold Only show messages if delay is greater than this limit
@@ -76,20 +76,26 @@ validate_response <- function(r){
7676
# @return the result of curl_fetch_memory(uri, handle)
7777
#
7878
try_fetch <- function(uri, handle,
79-
retry_on = c(400, 401, 440, 503, 504, 509),
80-
tries = 6,
79+
retry_on = c(400, 401, 440, 503, 504, 509),
80+
no_retry_on,
81+
.retry = 6,
8182
delay = 1, exponent = 2,
8283
no_message_threshold = 1)
8384
{
8485
r = curl_fetch_memory(uri, handle)
85-
# if(r$status_code == 400) validate_response(r)
86+
# if(r$status_code == 400){
87+
# validate_response(r)
88+
# }
89+
if(!missing(no_retry_on) && !is.null(no_retry_on)){
90+
retry_on <- setdiff(retry_on, no_retry_on)
91+
}
8692
if(!(r$status_code %in% retry_on)) {
8793
validate_response(r)
8894
return(r)
8995
}
9096
collisions = 1
9197
printed_message <- FALSE
92-
while(collisions < (tries)) {
98+
while(collisions < (.retry)) {
9399
r = curl_fetch_memory(uri, handle)
94100
if(!(r$status_code %in% retry_on)) {
95101
validate_response(r)

R/internal.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ get_datasets <- function(ws) {
3939
h = new_handle()
4040
handle_setheaders(h, .list = ws$.headers)
4141
uri <- sprintf("%s/workspaces/%s/datasources", ws$.studioapi, ws$id)
42-
r <- try_fetch(uri = uri, handle = h, delay = 0.25, tries = 3)
42+
r <- try_fetch(uri = uri, handle = h, delay = 0.25, .retry = 3)
4343

4444
msg <- paste("No results returned from datasets(ws).",
4545
"Please check your workspace credentials and api_endpoint are correct.")
@@ -89,7 +89,7 @@ get_experiments <- function(ws) {
8989
h = new_handle()
9090
handle_setheaders(h, .list=ws$.headers)
9191
uri = sprintf("%s/workspaces/%s/experiments", ws$.studioapi, ws$id)
92-
r <- try_fetch(uri = uri, handle = h, delay = 0.25, tries = 3)
92+
r <- try_fetch(uri = uri, handle = h, delay = 0.25, .retry = 3)
9393

9494
msg <- paste("No results returned from experiments(ws).",
9595
"Please check your workspace credentials and api_endpoint are correct.")

R/publish.R

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#' @export
3030
#'
3131
#' @inheritParams refresh
32+
#' @inheritParams workspace
3233
#' @param fun a function to publish; the function must have at least one argument.
3334
#' @param name name of the new web service; ignored when \code{serviceId} is specified (when updating an existing web service).
3435
#'
@@ -43,6 +44,7 @@
4344
#' @param serviceId optional Azure web service ID; use to update an existing service (see Note below).
4445
#' @param host optional Azure regional host, defaulting to the global \code{management_endpoint} set in \code{\link{workspace}}
4546
#' @param data.frame \code{TRUE} indicates that the function \code{fun} accepts a data frame as input and returns a data frame output; automatically set to \code{TRUE} when \code{inputSchema} is a data frame.
47+
#' @param .retry number of tries before failing
4648
#'
4749
#' @return A data.frame describing the new service endpoints, cf. \code{\link{endpoints}}. The output can be directly used by the \code{\link{consume}} function.
4850
#'
@@ -83,11 +85,12 @@
8385
#' @importFrom uuid UUIDgenerate
8486
#' @importFrom curl new_handle handle_setheaders handle_setopt
8587
publishWebService <- function(ws, fun, name,
86-
inputSchema, outputSchema, `data.frame`=FALSE,
87-
export=character(0),
88-
noexport=character(0),
88+
inputSchema, outputSchema,
89+
`data.frame` = FALSE,
90+
export = character(0),
91+
noexport = character(0),
8992
packages,
90-
version="3.1.0",
93+
version = "3.1.0",
9194
serviceId,
9295
host = ws$.management_endpoint,
9396
.retry = 3)
@@ -130,18 +133,7 @@ publishWebService <- function(ws, fun, name,
130133
}
131134

132135
}
133-
# inputSchema <- azureSchema(inputSchema)
134-
# outputSchema <- azureSchema(outputSchema)
135-
# if(`data.frame`) {
136-
# if(length(formals(fun)) != 1) {
137-
# stop("when data.frame=TRUE fun must only take one data.frame argument")
138-
# }
139-
# } else {
140-
# if(length(formals(fun)) != length(inputSchema)) {
141-
# stop("length(inputSchema) does not match the number of function arguments")
142-
# }
143-
# }
144-
136+
145137
### Get and encode the dependencies
146138

147139
if(missing(packages)) packages=NULL
@@ -191,7 +183,7 @@ publishWebService <- function(ws, fun, name,
191183
)
192184
handle_setheaders(h, .list = httpheader)
193185
handle_setopt(h, .list = opts)
194-
r = try_fetch(publishURL, handle = h, tries = .retry)
186+
r = try_fetch(publishURL, handle = h, .retry = .retry)
195187
result = rawToChar(r$content)
196188
if(r$status_code >= 400) stop(result)
197189
newService = fromJSON(result)

R/services.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ services <- function(ws, service_id, name, host = ws$.management_endpoint)
7575
}
7676

7777
uri <- sprintf("%s/workspaces/%s/webservices%s", host, ws$id, service_id)
78-
r <- try_fetch(uri = uri, handle = h, delay = 0.25, tries = 3)
78+
r <- try_fetch(uri = uri, handle = h, delay = 0.25, .retry = 3)
7979
# if(inherits(r, "error")){
8080
# msg <- paste("No results returned from datasets(ws).",
8181
# "Please check your workspace credentials and api_endpoint are correct.")

R/workspace.R

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,51 @@ default_api <- function(api_endpoint = "https://studioapi.azureml.net"){
7373
#' \if{html}{\figure{authorization_token.png}{options: width="60\%" alt="Figure: authorization_token.png"}}
7474
#' \if{latex}{\figure{authorizationToken.pdf}{options: width=7cm}}
7575
#'
76-
#' @section Using a \code{settings.json} file:
76+
#'
77+
#' @section Using a settings.json file:
7778
#' If any of the \code{id}, \code{auth}, \code{api_endpoint} or \code{management_endpoint} arguments are missing, the function attempts to read values from the \code{config} file with JSON format:
7879
#' \preformatted{
7980
#' {"workspace":{
8081
#' "id": "enter your AzureML workspace id here",
8182
#' "authorization_token": "enter your AzureML authorization token here",
8283
#' "api_endpoint": "https://studioapi.azureml.net",
84+
#' }}
85+
#' }
86+
#'
87+
#' To explicitly add the management endpoint in the JSON file, use:
88+
#' \preformatted{
89+
#' {"workspace":{
90+
#' "id": "enter your AzureML workspace id here",
91+
#' "authorization_token": "enter your AzureML authorization token here",
92+
#' "api_endpoint": "https://studioapi.azureml.net",
8393
#' "management_endpoint": "https://management.azureml.net"
8494
#' }}
8595
#' }
96+
#'
97+
#' @section Using a workspace in different Azure Machine Learning regions:
98+
#'
99+
#' By default, the Azure Machine Learning workspace is located in US South Central, but it is possible to create a workspace in different regions, including Europe West and Asia Southeast.
100+
#'
101+
#' To use a workspace in Asia Southeast, you can modify the api endpoint line in the JSON file:
102+
#' \preformatted{
103+
#' {"workspace": {
104+
#' "api_endpoint": ["https://asiasoutheast.studio.azureml.net"]
105+
#' }}
106+
#' }
107+
#'
108+
#' Similarly, for a workspace in Europe West:
109+
#' \preformatted{
110+
#' {"workspace": {
111+
#' "api_endpoint": ["https://europewest.studio.azureml.net"]
112+
#' }}
113+
#' }
114+
#'
86115

87116
#'
88117
#'
89118
#' @param id Optional workspace id from ML studio -> settings -> WORKSPACE ID. See the section "Finding your AzureML credentials" for more details.
90119
#' @param auth Optional authorization token from ML studio -> settings -> AUTHORIZATION TOKENS. See the section "Finding your AzureML credentials" for more details.
91-
#' @param api_endpoint Optional AzureML API web service URI. Defaults to \code{https://studioap.azureml.net} if not provided and not specified in config. See note.
120+
#' @param api_endpoint Optional AzureML API web service URI. Defaults to \code{https://studioapi.azureml.net} if not provided and not specified in config. See note.
92121
#' @param management_endpoint Optional AzureML management web service URI. Defaults to \code{https://management.azureml.net} if not provided and not specified in config. See note.
93122
#' @param config Optional settings file containing id and authorization info. Used if any of the other arguments are missing. The default config file is \code{~/.azureml/settings.json}, but you can change this location by setting \code{options(AzureML.config = "newlocation")}. See the section "Using a settings.json file" for more details.
94123
#' @param ... ignored

0 commit comments

Comments
 (0)