Skip to content

Commit

Permalink
add load/save methods
Browse files Browse the repository at this point in the history
  • Loading branch information
hongooi73 committed May 25, 2023
1 parent f7b9ee0 commit 081d06b
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Imports:
AzureGraph (>= 1.3.1),
utils,
parallel,
tools,
curl,
httr,
jsonlite,
Expand All @@ -32,6 +33,7 @@ Suggests:
rmarkdown,
testthat,
blastula,
emayili
emayili,
readr
Roxygen: list(markdown=TRUE, r6=FALSE)
RoxygenNote: 7.2.1
87 changes: 87 additions & 0 deletions R/ms_drive_item.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
#' - `get_parent_folder()`: Get the parent folder for this item, as a drive item object. Returns the root folder for the root. Not supported for remote items.
#' - `get_path()`: Get the absolute path for this item, as a character string. Not supported for remote items.
#' - `is_folder()`: Information function, returns TRUE if this item is a folder.
#' - `load_dataframe(delim=NULL, ...)`: Download a delimited file and return its contents as a data frame. See 'Convenience methods' below.
#' - `load_rds()`: Download a .rds file and return the saved object.
#' - `load_rdata(envir)`: Load a .RData or .Rda file into the specified environment.
#' - `save_dataframe(df, file, delim=",", ...)` Save a dataframe to a delimited file.
#' - `save_rds(object, file)`: Save an R object to a .rds file.
#' - `save_rdata(..., file)`: Save the specified objects to a .RData file.
#'
#' @section Initialization:
#' Creating new objects of this class should be done via the `get_item` method of the [`ms_drive`] class. Calling the `new()` method for this class only constructs the R object; it does not call the Microsoft Graph API to retrieve or create the actual item.
Expand Down Expand Up @@ -67,6 +73,15 @@
#'
#' This method returns a URL to access the item, for `type="view"` or "`type=edit"`. For `type="embed"`, it returns a list with components `webUrl` containing the URL, and `webHtml` containing a HTML fragment to embed the link in an IFRAME. The default is a viewable link, expiring in 7 days.
#'
#' @section Convenience methods:
#' The following methods are provided to simplify the task of loading and saving datasets and R objects.
#' - `load_dataframe` downloads a delimited file and returns its contents as a data frame. The delimiter can be specified with the `delim` argument; if omitted, this is "," if the file extension is .csv, ";" if the file extension is .csv2, and a tab otherwise. If the readr package is installed, the `readr::read_delim` function is used to parse the file, otherwise `utils::read.delim` is used. You can supply other arguments to the parsing function via the `...` argument.
#' - `save_dataframe` is the inverse of `load_dataframe`: it uploads the given data frame to a folder item. Specify the delimiter with the `delim` argument. The `readr::write_delim` function is used to serialise the data if that package is installed, and `utils::write.table` otherwise.
#' - `load_rds` downloads a .rds file and returns its contents as an R object. It is analogous to the base `readRDS` function but for OneDrive/SharePoint drive items.
#' - `save_rds` uploads a given R object as a .rds file, analogously to `saveRDS`.
#' - `load_rdata` downloads a .RData or .Rda file and loads its contents into the given environment. It is analogous to the base `load` function but for OneDrive/SharePoint drive items.
#' - `save_rdata` uploads the given R objects as a .RData file, analogously to `save`.
#'
#' @section List methods:
#' All `list_*` methods have `filter` and `n` arguments to limit the number of results. The former should be an [OData expression](https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter) as a string to filter the result set on. The latter should be a number setting the maximum number of (filtered) results to return. The default values are `filter=NULL` and `n=Inf`. If `n=NULL`, the `ms_graph_pager` iterator object is returned instead to allow manual iteration over the results.
#'
Expand Down Expand Up @@ -376,6 +391,71 @@ public=list(
else private$download_file(dest, overwrite)
},

load_dataframe=function(delim=NULL, ...)
{
private$assert_is_file()
ext <- tolower(tools::file_ext(self$properties$name))
if(is.null(delim))
{
delim <- if(ext == "csv") "," else if(ext == "csv2") ";" else "\t"
}
dat <- self$download(NULL)
if(requireNamespace("readr"))
{
con <- rawConnection(dat, "r")
on.exit(try(close(con), silent=TRUE))
readr::read_delim(con, delim=delim)
}
else utils::read.delim(text=rawToChar(dat), sep=delim, ...)
},

load_rdata=function(envir=parent.frame())
{
private$assert_is_file()
private$assert_file_extension_is("rdata", "rda")
rdata <- self$download(NULL)
load(rawConnection(rdata, open="rb"), envir=envir)
},

load_rds=function()
{
private$assert_is_file()
private$assert_file_extension_is("rds")
rds <- self$download(NULL)
unserialize(memDecompress(rds))
},

save_dataframe=function(df, file, delim=",", ...)
{
private$assert_is_folder()
conn <- rawConnection(raw(0), open="r+b")
if(requireNamespace("readr"))
readr::write_delim(df, conn, delim=delim, ...)
else utils::write.table(df, conn, sep=delim, ...)
seek(conn, 0)
self$upload(conn, file)
},

save_rdata=function(..., file, envir=parent.frame())
{
private$assert_is_folder()
# save to a temporary file as saving to a connection disables compression
tmpsave <- tempfile(fileext=".rdata")
on.exit(unlink(tmpsave))
save(..., file=tmpsave, envir=envir)
self$upload(tmpsave, file)
},

save_rds=function(object, file)
{
private$assert_is_folder()
# save to a temporary file to avoid dealing with memCompress/memDecompress hassles
tmpsave <- tempfile(fileext=".rdata")
on.exit(unlink(tmpsave))
saveRDS(object, tmpsave)
self$upload(tmpsave, file)
},

get_path=function()
{
private$assert_is_not_remote()
Expand Down Expand Up @@ -544,6 +624,13 @@ private=list(
{
if(!is.null(self$properties$remoteItem))
stop("This method is not applicable for a remote item", call.=FALSE)
},

assert_file_extension_is=function(...)
{
ext <- tolower(tools::file_ext(self$properties$name))
if(!(ext %in% unlist(list(...))))
stop("Not an allowed file type")
}
))

Expand Down
19 changes: 19 additions & 0 deletions man/ms_drive_item.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 081d06b

Please sign in to comment.