Skip to content
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

Some fixes #13

Merged
merged 8 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: cloudfs
Title: Streamlined Interface to Interact with Cloud Storage Platforms
Version: 0.1.2.9000
Version: 0.1.3
Authors@R: c(
person("Iaroslav", "Domin", email = "[email protected]", role = c("aut", "cre")),
person("Stefan", "Musch", email = "[email protected]", role = c("aut")),
Expand All @@ -15,7 +15,7 @@ Description: A unified interface for simplifying cloud storage interactions,
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
Imports:
aws.s3,
googledrive,
Expand Down
7 changes: 6 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# cloudfs (development version)
# cloudfs 0.1.3

* Updated `cloud_object_ls()` to support paths containing spaces.
* Improved various sections of the documentation.
* Enabled multipart upload for S3 writing and uploading functions, with the
default part size of 100 MB.

# cloudfs 0.1.2

Expand Down
32 changes: 32 additions & 0 deletions R/cli.R
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,35 @@ check_bool <- function(x, alt_null = FALSE, add_msg = NULL) {
))
}
}


#' @title Validate a path
#'
#' @description Makes sure that a path passed to a cloud function is in the
#' right format.
#'
#' @param path A path relative to the project folder root. Can contain only
#' letters, digits, '-', '_', '.', spaces and '/' symbols.
#' @param error if `TRUE` (default), throws an error if `file` is not a valid
#' file path.
#'
#' @return Either `TRUE` or `FALSE` if `error` is `FALSE`. Either `TRUE` or
#' an error if `error` is `TRUE`.
#'
#' @keywords internal
check_path <- function(path, error = TRUE) {
res <- grepl("^([A-Za-z]|[0-9]|-|_|\\.| |/)+$", path)
if (error) {
if (path == "") cli::cli_abort("A valid path must not be empty.")
if (!res) cli_abort(c(
"Path '{path}' is not valid",
"A valid path must consist of:",
"*" = "uppercase/lowercase letters",
"*" = "digits",
"*" = "'/' symbols to separate directories in the path",
"*" = "'_', '-', '.' symbols or spaces"
))
}
res
}

14 changes: 2 additions & 12 deletions R/cloud_local.R
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,12 @@ cloud_object_ls <- function(x, path, extension, prefix = "", suffix = "") {
check_string(extension)
check_string(prefix)
check_string(suffix)

if (!grepl("^([A-Za-z]|[0-9]|-|_|\\.|/)+$", path)) {
cli::cli_abort(c(
"Directory path {.path {path}} is not valid. A valid directory path may \\
consist of:",
"*" = "uppercase/lowercase letters",
"*" = "digits",
"*" = "'/' symbols to describe its location inside project's folder",
"*" = "'_', '-', '.' symbols or spaces."
))
}
check_path(path)

if (!grepl("^([A-Za-z]|[0-9])+$", extension)) {
cli::cli_abort(c(
"{.arg extension} {.val {extension}} is not valid. A valid extension path \\
may consist of:",
must consist of:",
"*" = "uppercase/lowercase letters",
"*" = "digits"
))
Expand Down
32 changes: 0 additions & 32 deletions R/common.R
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,6 @@ proj_desc_get <- function(key, project = ".") {
unname(value)
}

#' @title Validate file path for cloud functions
#'
#' @description Makes sure that file path passed to a cloud function is in the
#' right format.
#'
#' @param file Path to a file relative to project folder root. Can contain only
#' letters, digits, '-', '_', '.', spaces and '/' symbols.
#' @param error if `TRUE` (default), throws an error if `file` is not a valid
#' file path.
#'
#' @return Either `TRUE` or `FALSE` if `error` is `FALSE`. Either `TRUE` or
#' an error if `error` is `TRUE`.
#'
#' @keywords internal
cloud_validate_file_path <- function(file, error = TRUE) {
check_string(file)
res <- grepl("^([A-Za-z]|[0-9]|-|_|\\.| |/)+$", file)
if (error) {
if (file == "") cli::cli_abort("A valid file name should not be empty.")
if (!res) cli_abort(c(
"File name '{file}' is not valid",
"A valid file name may consist of:",
"*" = "uppercase/lowercase letters",
"*" = "digits",
"*" = "spaces",
"*" = "'/' symbols to describe its location inside project's folder",
"*" = "'_', '-', '.' symbols"
))
}
res
}

#' @title Validate file names
#'
#' @description Given a character vector of filenames checks that all names pass
Expand Down
28 changes: 28 additions & 0 deletions R/doc.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#' @title Package-wide description of `file` parameter
#' @description A dummy function to be referred by `@inheritParams` for a
#' parameter documentation.
#'
#' @param file Path to a file relative to project folder root. Can contain only
#' letters, digits, '-', '_', '.', spaces and '/' symbols.
#'
#' @keywords internal
doc_file <- function(file) {}



#' @title Package-wide description of `local` parameter
#' @description A dummy function to be referred by `@inheritParams` for a
#' parameter documentation.
#'
#' @param local Logical, defaulting to `FALSE`. If `TRUE`, the function will
#' also create a local copy of the file at the specified path. Note that some
#' writing functions might not overwrite existing files unless explicitly
#' allowed. Typically, such functions have a parameter (often named
#' `overwrite`) to control this behavior. Check the documentation of the
#' writing function used to determine the exact parameter name and pass it
#' through the `...` argument if necessary. Alternatively, you can define an
#' anonymous function for `fun` that calls a writing function with the
#' overwriting option enabled.
#'
#' @keywords internal
doc_local <- function(local) {}
19 changes: 9 additions & 10 deletions R/drive_transfer.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @description Uploads a local file from the project's directory to its
#' corresponding location within the project's Google Drive root folder.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#' @inheritParams cloud_drive_ls
#'
#' @inherit cloud_drive_find_path details
Expand All @@ -25,7 +25,7 @@
#'
#' @export
cloud_drive_upload <- function(file, root = NULL) {
cloud_validate_file_path(file)
check_path(file)

if (!file.exists(file)) {
cli::cli_abort("File {.path {file}} does not exist.")
Expand All @@ -51,7 +51,7 @@ cloud_drive_upload <- function(file, root = NULL) {
#' saves it to the local project folder, maintaining the original folder
#' structure.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#' @inheritParams cloud_drive_ls
#'
#' @inherit cloud_drive_find_path details
Expand All @@ -68,7 +68,7 @@ cloud_drive_upload <- function(file, root = NULL) {
#'
#' @export
cloud_drive_download <- function(file, root = NULL) {
cloud_validate_file_path(file)
check_path(file)

check_string(root, alt_null = TRUE)
if (is.null(root)) root <- cloud_drive_get_root()
Expand All @@ -95,15 +95,14 @@ cloud_drive_download <- function(file, root = NULL) {
#' function will infer the appropriate writing method based on the file's
#' extension.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#' @inheritParams cloud_drive_ls
#' @inheritParams doc_local
#'
#' @param x An R object to be written to Google Drive.
#' @param fun A custom writing function. If `NULL` (default), the appropriate
#' writing function will be inferred based on the file's extension.
#' @param ... Additional arguments to pass to the writing function `fun`.
#' @param local Logical. If `TRUE`, a local copy of the file will also be
#' created at the specified path. Default is `FALSE`.
#'
#' @inheritSection cloud_guess_write_fun Default writing functions
#'
Expand All @@ -121,7 +120,7 @@ cloud_drive_download <- function(file, root = NULL) {
#' @export
cloud_drive_write <- function(x, file, fun = NULL, ..., local = FALSE,
root = NULL) {
cloud_validate_file_path(file)
check_path(file)
check_bool(local)

if (is.null(fun)) {
Expand Down Expand Up @@ -162,7 +161,7 @@ cloud_drive_write <- function(x, file, fun = NULL, ..., local = FALSE,
#' reading function based on the file's extension. However, you can specify a
#' custom reading function if necessary.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#' @inheritParams cloud_drive_ls
#'
#' @param fun A custom reading function. If `NULL` (default), the appropriate
Expand All @@ -185,7 +184,7 @@ cloud_drive_write <- function(x, file, fun = NULL, ..., local = FALSE,
#'
#' @export
cloud_drive_read <- function(file, fun = NULL, ..., root = NULL) {
cloud_validate_file_path(file)
check_path(file)
if (is.null(fun)) {
fun <- cloud_guess_read_fun(file)
}
Expand Down
6 changes: 3 additions & 3 deletions R/drive_utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ cloud_drive_download_by_id <- function(file, path, overwrite = FALSE) {
#'
#' @noRd
cloud_drive_guess_type <- function(file) {
cloud_validate_file_path(file)
check_path(file)
ext <- tolower(tools::file_ext(file))
switch (
ext,
Expand Down Expand Up @@ -112,7 +112,7 @@ cloud_drive_put <- function(media, path) {
#' @description Finds the spreadsheet by path relative to a project root.
#' Applies [googlesheets4::range_autofit()] to each sheet.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#' @inheritParams cloud_drive_ls
#'
#' @return The file ID of the resized Google spreadsheet as an invisible result.
Expand All @@ -123,7 +123,7 @@ cloud_drive_put <- function(media, path) {
#'
#' @export
cloud_drive_spreadsheet_autofit <- function(file, root = NULL) {
cloud_validate_file_path(file)
check_path(file)
check_string(root, alt_null = TRUE)

if (is.null(root)) root <- cloud_drive_get_root()
Expand Down
8 changes: 4 additions & 4 deletions R/read_write.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @description Take a look at the switch call. That's basically it. Returns an
#' appropriate function or throws an error if wasn't able to find one.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#'
#' @section Default writing functions:
#'
Expand All @@ -21,7 +21,7 @@
#'
#' @keywords internal
cloud_guess_write_fun <- function(file) {
cloud_validate_file_path(file)
check_path(file)
ext <- tolower(tools::file_ext(file))
if (ext == "") stop("Missing file extension, unable to guess writing function.")
fun <- switch (
Expand All @@ -47,7 +47,7 @@ cloud_guess_write_fun <- function(file) {
#' @description Take a look at the switch call. That's basically it. Returns an
#' appropriate function or throws an error if wasn't able to find one.
#'
#' @inheritParams cloud_validate_file_path
#' @inheritParams doc_file
#'
#' @section Default reading functions:
#'
Expand All @@ -64,7 +64,7 @@ cloud_guess_write_fun <- function(file) {
#'
#' @keywords internal
cloud_guess_read_fun <- function(file) {
cloud_validate_file_path(file)
check_path(file)
ext <- tolower(tools::file_ext(file))
if (ext == "") stop("Missing file extension, unable to guess reading function.")
fun <- switch (
Expand Down
Loading
Loading