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

feat: add write_datasources an fix pkgdown #56

Merged
merged 4 commits into from
Dec 17, 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
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: connector
Title: Connect to your data easily
Version: 0.0.4.9000
Version: 0.0.4.9001
Authors@R: c(
person("Cervan", "Girard", , "[email protected]", role = c("aut", "cre")),
person("Aksel", "Thomsen", , "[email protected]", role = "aut"),
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ S3method(write_cnt,connector_dbi)
S3method(write_cnt,connector_fs)
S3method(write_cnt,default)
S3method(write_ext,csv)
S3method(write_ext,json)
S3method(write_ext,parquet)
S3method(write_ext,rds)
S3method(write_ext,txt)
Expand All @@ -63,6 +64,7 @@ export(remove_directory_cnt)
export(tbl_cnt)
export(upload_cnt)
export(write_cnt)
export(write_datasources)
export(write_ext)
export(write_file)
import(rlang)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# connector dev

- Connectors constructor builds the datasources attribute
- Ability to write datasources attribute to a configuration file
- Create a new class for nested connectors objects, "nested_connectors"
- Add README and vignette on how to extend connector

Expand Down
2 changes: 1 addition & 1 deletion R/connect.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#' @param datasource [character] Name(s) of the datasource(s) to connect to.
#' If `NULL` (the default) all datasources are connected.
#' @param set_env [logical] Should environment variables from the yaml file be set? Default is TRUE.
#' @param logging [logical] Add logs to the console as well as to the whirl log html files. See details with this vignette.

Check warning on line 36 in R/connect.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connect.R,line=36,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 123 characters.
#' @return [connectors]
#'
#' @examples
Expand Down Expand Up @@ -82,7 +82,7 @@
checkmate::assert_logical(logging)

if (!is.list(config)) {
if (get_file_ext(config) %in% c("yml", "yaml")) {
if (tools::file_ext(config) %in% c("yml", "yaml")) {
config <- read_file(config, eval.expr = TRUE)
} else {
config <- read_file(config)
Expand Down Expand Up @@ -129,12 +129,12 @@
purrr::map(create_connection) |>
rlang::set_names(purrr::map_chr(config$datasources, list("name", 1)))

## clean datasources

Check warning on line 132 in R/connect.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connect.R,line=132,col=4,[indentation_linter] Indentation should be 2 spaces but is 4 spaces.
# unlist name of datasource
for(i in seq_along(config$datasources)){

Check warning on line 134 in R/connect.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connect.R,line=134,col=6,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
config$datasources[[i]]$name <- config$datasources[[i]]$name[[1]]
}

Check warning on line 137 in R/connect.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connect.R,line=137,col=1,[trailing_whitespace_linter] Trailing whitespace is superfluous.
connections$datasources <- as_datasources(config["datasources"])

do.call(what = connectors, args = connections)
Expand Down
19 changes: 14 additions & 5 deletions R/connectors.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
connectors <- function(...) {
x <- rlang::list2(...)
ds_ <- x[["datasources"]]

if (!is.null(ds_) & !inherits(ds_, "cnts_datasources")) {

Check warning on line 32 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=32,col=21,[vector_logic_linter] Conditional expressions require scalar logical operators (&& and ||)
cli::cli_abort("'datasources' is a reserved name. It cannot be used as a name for a data source.")
}

Expand Down Expand Up @@ -79,7 +79,7 @@
print.cnts_datasources <- function(x, ...) {
cli::cli_h1("Datasources")

for(ds in x[["datasources"]]) {

Check warning on line 82 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=82,col=1,[indentation_linter] Indentation should be 2 spaces but is 1 spaces.

Check warning on line 82 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=82,col=5,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
cli::cli_h2(ds$name)
cli::cli_ul()
cli::cli_li("Backend Type: {.val {ds$backend$type}}")
Expand All @@ -90,7 +90,7 @@
cli::cli_end()
}

return(x)

Check warning on line 93 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=93,col=1,[indentation_linter] Indentation should be 2 spaces but is 1 spaces.
}

#' @noRd
Expand All @@ -115,16 +115,20 @@
#' modification.
#'
#' @examples
#' # Assume we have a 'my_connectors' object with a 'datasources' attribute
#' my_connectors <- list()
#' attr(my_connectors, "datasources") <- list(source1 = "data1", source2 = "data2")
#' # Assume we have a 'mock_connectors' object with a 'datasources' attribute
#' mock_connectors <- structure(list(), class = "connectors" )
#' attr(mock_connectors, "datasources") <- list(source1 = "data1", source2 = "data2")
#'
#' # Using the function
#' result <- datasources(my_connectors)
#' result <- datasources(mock_connectors)
#' print(result)
#'
#' @export
datasources <- function(connectors) {
if(!is_connectors(connectors)){

Check warning on line 128 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=128,col=5,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.

Check warning on line 128 in R/connectors.R

View workflow job for this annotation

GitHub Actions / Megalinter / MegaLinter

file=/github/workspace/R/connectors.R,line=128,col=33,[brace_linter] There should be a space before an opening curly brace.
cli::cli_abort("param connectors should be a connectors object.")
}

ds <- attr(connectors, "datasources")
ds
}
Expand All @@ -149,3 +153,8 @@
print.nested_connectors <- function(x, ...) {
print_connectors(x, ...)
}

#' @noRd
is_connectors <- function(connectors){
inherits(connectors, "connectors")
}
96 changes: 76 additions & 20 deletions R/conts_datasources.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#' @param data A list of function calls as expressions.
#' @return A list with a 'datasources' element containing the transformed backends.
#'
#'
#' @noRd
connectors_to_datasources <- function(data) {
data[-1] |>
as.list() |>
Expand All @@ -19,17 +19,66 @@ connectors_to_datasources <- function(data) {
transform_as_datasources()
}

#' Write datasources attribute into a config file
#'
#' Reproduce your workflow by creating a config file based on a connectors
#' object and the associated datasource attributes.
#'
#' @param connectors A connectors object with associated "datasources"
#' attribute.
#' @param file path to the config file
#'
#' @return A config file with datasource attributes which can be reused in the
#' connect function
#'
#' @examples
#'
#' # Connect to the datasources specified in it
#' config <- system.file("config", "default_config.yml", package = "connector")
#' cnts <- connect(config)
#'
#' # Extract the datasources to a config file
#' yml_file <- tempfile(fileext = ".yml")
#' write_datasources(cnts, yml_file)
#'
#' # Reconnect using the new config file
#' re_connect <- connect(yml_file)
#' re_connect
#'
#' @export
write_datasources <- function(connectors, file) {
checkmate::assert_character(file, null.ok = FALSE, any.missing = FALSE)
if (!is_connectors(connectors)) {
cli::cli_abort("param 'connectors' should be a connectors object.")
}
# testing extension of file
ext <- tools::file_ext(file)
stopifnot(ext %in% c("yaml", "yml", "json", "rds"))
## using our own write function from connector
dts <- datasources(connectors)

## Remove class for json to avoid S3 class problem
if (ext == "json") {
class(dts) <- NULL
}

write_file(dts, file)
}

#' Transform Clean Function Info to Backend Format
#'
#' This function takes the output of `extract_function_info` and transforms it
#' into a backend format suitable for further processing or API integration.
#'
#' @param infos A list with class "clean_fct_info", typically the output of `extract_function_info`.
#' @param name A character string representing the name to be assigned to the backend.
#' @param infos A list with class "clean_fct_info", typically the output of
#' `extract_function_info`.
#' @param name A character string representing the name to be assigned to the
#' backend.
#'
#' @return A list representing the backend, with 'name' and 'backend' components or an error if the input is not of class "clean_fct_info".
#' @return A list representing the backend, with 'name' and 'backend' components
#' or an error if the input is not of class "clean_fct_info".
#'
#' @keywords internal
#' @noRd
transform_as_backend <- function(infos, name) {
if (!inherits(infos, "clean_fct_info")) {
cli::cli_abort("You should use the extract_function_info function before calling this function")
Expand All @@ -49,15 +98,18 @@ transform_as_backend <- function(infos, name) {

#' Transform Multiple Backends to Datasources Format
#'
#' This function takes a list of backends (typically created by `transform_as_backend`)
#' and wraps them in a 'datasources' list. This is useful for creating a structure
#' that represents multiple data sources or backends.
#' This function takes a list of backends (typically created by
#' `transform_as_backend`) and wraps them in a 'datasources' list. This is
#' useful for creating a structure that represents multiple data sources or
#' backends.
#'
#' @param bks A list of backends, each typically created by `transform_as_backend`.
#' @param bks A list of backends, each typically created by
#' `transform_as_backend`.
#'
#' @return A list with a single 'datasources' element containing all input backends.
#' @return A list with a single 'datasources' element containing all input
#' backends.
#'
#' @keywords internal
#' @noRd
transform_as_datasources <- function(bks) {
as_datasources(
list(
Expand All @@ -77,6 +129,8 @@ transform_as_datasources <- function(bks) {
#' \item{parameters}{A list of parameters passed to the function}
#' \item{is_r6}{A boolean indicating whether it's an R6 class constructor}
#' \item{package_name}{The name of the package containing the function}
#' @noRd
#'
extract_function_info <- function(func_string) {
# Parse the function string into an expression

Expand Down Expand Up @@ -115,12 +169,14 @@ extract_function_info <- function(func_string) {

#' Extract Base Information
#'
#' Extracts the package name and function/class name from the full function name.
#' Extracts the package name and function/class name from the full function
#' name.
#'
#' @param full_func_name The full name of the function (potentially including package).
#' @param full_func_name The full name of the function (potentially including
#' package).
#' @param is_r6 Boolean indicating whether it's an R6 class constructor.
#' @return A list with package_name and func_name.
#' @keywords internal
#' @noRd
extract_base_info <- function(full_func_name, is_r6) {
# Check if the function name includes a package specification
if (grepl("::", full_func_name, fixed = TRUE)) {
Expand Down Expand Up @@ -158,7 +214,7 @@ extract_base_info <- function(full_func_name, is_r6) {
#' @param package_name The name of the package containing the function.
#' @param func_name The name of the function.
#' @return A list with the function object and its formal arguments.
#' @keywords internal
#' @noRd
get_standard_specific_info <- function(package_name, func_name) {
func <- getExportedValue(package_name, func_name)
formal_args <- names(formals(func))
Expand All @@ -172,7 +228,7 @@ get_standard_specific_info <- function(package_name, func_name) {
#' @param package_name The name of the package containing the R6 class.
#' @param func_name The name of the R6 class.
#' @return A list with the initialize method and its formal arguments.
#' @keywords internal
#' @noRd
get_r6_specific_info <- function(package_name, func_name) {
class_obj <- getExportedValue(package_name, func_name)
init_func <- class_obj$public_methods$initialize
Expand All @@ -187,8 +243,8 @@ get_r6_specific_info <- function(package_name, func_name) {
#' @param expr The parsed expression of the function call.
#' @param formal_args The formal arguments of the function.
#' @return A list of processed parameters.
#' @keywords internal
#'
#' @noRd
#'
extract_and_process_params <- function(expr, formal_args) {
# Extract parameters from the function call
params <- call_args(expr)
Expand Down Expand Up @@ -218,7 +274,7 @@ extract_and_process_params <- function(expr, formal_args) {
#'
#' @param params The extracted parameters from the function call.
#' @return A list of processed parameters.
#' @keywords internal
#' @noRd
process_ellipsis_params <- function(params) {
unnamed_args <- params[names(params) == ""]
named_args <- params[names(params) != ""]
Expand All @@ -233,7 +289,7 @@ process_ellipsis_params <- function(params) {
#' @param params The extracted parameters from the function call.
#' @param formal_args The formal arguments of the function.
#' @return A list of processed parameters.
#' @keywords internal
#' @noRd
process_named_params <- function(params, formal_args) {
unnamed_args <- params[names(params) == ""]
named_args <- params[names(params) != ""]
Expand Down
2 changes: 1 addition & 1 deletion R/fs_read.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#' @return the result of the reading function
#' @export
read_file <- function(path, ...) {
find_ext <- get_file_ext(path)
find_ext <- tools::file_ext(path)

class(path) <- c(find_ext, class(path))

Expand Down
11 changes: 10 additions & 1 deletion R/fs_write.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#' @return `write_file()`: [invisible()] file.
#' @export
write_file <- function(x, file, ...) {
find_ext <- get_file_ext(file) |>
find_ext <- tools::file_ext(file) |>
assert_ext("write_ext")

class(file) <- c(find_ext, class(file))
Expand Down Expand Up @@ -93,3 +93,12 @@ write_ext.yml <- function(file, x, ...) {

#' @export
write_ext.yaml <- write_ext.yml

#' @description
#' * `json`: [jsonlite::write_json()]
#'
#' @rdname write_file
#' @export
write_ext.json <- function(file, x, ...) {
jsonlite::write_json(x = x, path = file, ...)
}
14 changes: 0 additions & 14 deletions R/utils_fileext.R

This file was deleted.

5 changes: 5 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ reference:
- connector
- connector_fs
- connector_dbi
- nested_connectors
- title: Connector functions
contents:
- matches(".*_cnt$")
- title: Read and write files
contents:
- read_file
- write_file
- write_datasources
- title: Utils
contents:
- datasources
18 changes: 0 additions & 18 deletions man/connectors_to_datasources.Rd

This file was deleted.

8 changes: 4 additions & 4 deletions man/datasources.Rd

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

20 changes: 0 additions & 20 deletions man/extract_and_process_params.Rd

This file was deleted.

Loading
Loading