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

Add function to parse previous text log file #166

Merged
merged 29 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
971eca8
add log reading functions
parmsam-pfizer Feb 22, 2023
4c7b760
add readr to DESCRIPTION file
parmsam-pfizer Mar 1, 2023
f7684d3
update documentation and style for tidy
parmsam-pfizer Mar 1, 2023
8d79eec
add unit test
parmsam-pfizer Mar 1, 2023
10d74dc
Update pkgdown site yml
parmsam-pfizer Mar 1, 2023
dd18281
Update newsmd with new read_log_file
parmsam-pfizer Mar 1, 2023
1c63ea3
Wrap predicate function in `where()`
parmsam-pfizer Mar 7, 2023
6b86210
default parsed log to already nested log
parmsam-pfizer Mar 14, 2023
de59b83
Merge branch '162_parse_log' of https://github.com/parmsam-pfizer/log…
parmsam-pfizer Mar 14, 2023
1d15668
Merge branch 'dev' into 162_parse_log
bms63 Jul 13, 2023
c25ee9b
resolve test-parse error
parmsam-pfizer Jul 24, 2023
a7ab459
Merge branch 'dev' into 162_parse_log
parmsam-pfizer Aug 10, 2023
58b0e29
Merge branch 'dev' into 162_parse_log
parmsam-pfizer Aug 21, 2023
0179b66
Update DESCRIPTION
parmsam-pfizer Aug 21, 2023
837c2de
add methods for lifecycle condition
parmsam-pfizer Aug 22, 2023
84d9e2d
declare methods pkg
parmsam-pfizer Aug 22, 2023
3158aa3
declare missing pkgs for funcs
parmsam-pfizer Aug 22, 2023
b101ea9
fix test to not include remove_log_object arg
parmsam-pfizer Aug 22, 2023
f02e451
Merge branch 'dev' into 162_parse_log
bms63 Sep 8, 2023
851f64a
Update DESCRIPTION
parmsam-pfizer Sep 8, 2023
480b2ba
Merge branch 'dev' into 162_parse_log
bms63 Sep 10, 2023
163e1d1
move readr to suggests
parmsam-pfizer Sep 12, 2023
597d3cc
ensure readr is checked for in read_ function
parmsam-pfizer Sep 12, 2023
e8f00b6
update test to check if suggest is available
parmsam-pfizer Sep 12, 2023
27f5c4b
remove readr from roxygen2 header importFrom
parmsam-pfizer Sep 12, 2023
5893100
add lifecycle and methods to imports, xml2 to suggests
parmsam-pfizer Sep 12, 2023
dc7f046
Merge branch 'dev' into 162_parse_log
bms63 Sep 13, 2023
6826254
reconcile description file
parmsam-pfizer Sep 13, 2023
f965531
remove mention of 'previous'
parmsam-pfizer Sep 13, 2023
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: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ Imports:
tibble,
digest,
lintr,
lifecycle
readr,
lifecycle,
methods
Suggests:
testthat (>= 3.0.0),
knitr,
Expand Down
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ importFrom(dplyr,distinct)
importFrom(dplyr,filter)
importFrom(dplyr,group_by)
importFrom(dplyr,mutate)
importFrom(dplyr,rename_with)
importFrom(dplyr,select)
importFrom(dplyr,ungroup)
importFrom(lintr,lint)
Expand All @@ -31,6 +32,7 @@ importFrom(purrr,map2_dfr)
importFrom(purrr,map_chr)
importFrom(purrr,safely)
importFrom(purrr,set_names)
importFrom(readr,read_table)
importFrom(rlang,.data)
importFrom(rstudioapi,selectDirectory)
importFrom(rstudioapi,selectFile)
Expand All @@ -51,14 +53,20 @@ importFrom(shiny,uiOutput)
importFrom(stats,aggregate)
importFrom(stringi,stri_wrap)
importFrom(stringr,str_c)
importFrom(stringr,str_count)
importFrom(stringr,str_detect)
importFrom(stringr,str_extract)
importFrom(stringr,str_remove)
importFrom(stringr,str_remove_all)
importFrom(stringr,str_replace)
importFrom(stringr,str_replace_all)
importFrom(stringr,str_starts)
importFrom(stringr,str_trim)
importFrom(tibble,tibble)
importFrom(tidyr,all_of)
importFrom(tidyr,complete)
importFrom(tidyr,pivot_wider)
importFrom(tidyr,separate)
importFrom(utils,capture.output)
importFrom(utils,getParseData)
importFrom(utils,lsf.str)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@

# logrx 0.3.0

- Add `show_repo_url` option in `axecute()` to capture repo URL(s) into log file (#167)
- Moved website theme to bootstarp 5, enabled search (#179)
- Add `include_rds` argument to `axecute()` to export log as rds file
- Add `read_log_file()` to read previous logrx log file
- Remove argument for remove_log_object from `axecute()` still accessible via `log_write()` (#182)

# logrx 0.2.2
Expand Down
2 changes: 1 addition & 1 deletion R/axecute.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ axecute <- function(file, log_name = NA,
show_repo_url = FALSE,
...){
# deprecations
if (hasArg(remove_log_object)) {
if (methods::hasArg(remove_log_object)) {
lifecycle::deprecate_stop("0.3.0", "axecute(remove_log_object = )", "axecute(include_rds = )")
}

Expand Down
284 changes: 284 additions & 0 deletions R/read_log_file.R
bms63 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
#' Reformat subsections in log lines
#'
#' @param log_txt String vector. Object with log text lines
#'
#' @importFrom stringr str_detect
#' @importFrom stringr str_count
#' @importFrom stringr str_remove
#'
#' @return tibble that ensures formatted subsections
#'
#' @examples
#' \dontrun{
#' reformat_subsections(readlines(log_file_path))
#' }
#'
#' @noRd
#'
reformat_subsections <- function(log_txt) {
adj_log_txt <- c()
for (i in log_txt) {
adj_tf <- stringr::str_detect(
i,
"Errors:|Warnings:|Messages:|Output:|Result:"
)
if (adj_tf) {
nrem <- stringr::str_count(i)
i <- stringr::str_remove(i, ":")
i <-
paste("-", i, paste(rep("-", 54 - nrem), collapse = ""),
collapse = ""
)
}
adj_log_txt <- c(adj_log_txt, i)
}
return(adj_log_txt)
}

#' Nest sections in log lines vector
#'
#' @param adj_log_txt String vector. Object with formatted log text lines
#'
#' @importFrom stringr str_remove_all
#'
#' @return list that includes nested log sections
#'
#' @noRd
#'
nest_sections <- function(adj_log_txt) {
sect_headers <- c()
sect_status <- FALSE
sect_info <- list()
for (i in adj_log_txt) {
if (i == paste(rep("-", 80), collapse = "")) {
sect_status <- !sect_status
} else if (sect_status == TRUE) {
sect_headers <- c(sect_headers, i)
} else {
cur_pos <- length(sect_headers)
if (length(sect_info) == cur_pos) {
sect_info[[cur_pos]] <- c(sect_info[[cur_pos]], i)
} else {
sect_info[[cur_pos]] <- i
}
}
}
sect_headers <-
stringr::str_remove_all(sect_headers, "-?\\s{3,}-?")
names(sect_info) <- sect_headers

return(sect_info)
}

#' Nest subsections in log lines vector
#'
#' @param adj_log_txt String vector. Object with formatted log text lines
#' @param sect_info String vector. Object with nested sections
#'
#' @importFrom stringr str_extract
#' @importFrom stringr str_trim
#' @importFrom stringr str_remove_all
#'
#' @return list that includes nested log subsections
#'
#' @noRd
#'
nest_subsections <- function(adj_log_txt, sect_info) {
subsect_headers <- stats::na.omit(
stringr::str_extract(adj_log_txt, "\\-\\s\\w+\\s(\\w+\\s)?\\-{3,70}")
)
subset_sections <- function(section) {
subsect_status <- FALSE
subsect_info <- list()
for (i in section) {
if (i %in% subsect_headers) {
latest_subsect <- stringr::str_trim(
stringr::str_remove_all(i, "\\-")
)
subsect_status <- TRUE
} else if (subsect_status) {
subsect_info[[latest_subsect]] <-
c(subsect_info[[latest_subsect]], i)
} else {
subsect_info <- c(subsect_info, i)
}
}
subsect_info
}
nested_log <- lapply(sect_info, subset_sections)
return(nested_log)
}

#' Nest sections and subsections in log lines vector
#'
#' @param adj_log_txt String vector. Object with formatted log text lines
#'
#' @return list that includes nested log sections and subsections
#'
#' @noRd
#'
nest_log <- function(adj_log_txt) {
nest_subsections(
adj_log_txt,
nest_sections(adj_log_txt)
)
}

#' Parse nested log list to tibbles for object where appropriate
#'
#' @param nested_log String vector.
#' Object with nested log output (from `nest_log()`)
#'
#' @importFrom tibble tibble
#' @importFrom tidyr separate
#' @importFrom stringr str_replace_all
#' @importFrom dplyr rename_with
#' @importFrom readr read_table
#' @importFrom dplyr mutate
#'
#' @return list with objects coerced as tibbles
#'
#' @noRd
#'
parse_log <- function(nested_log) {
parsed_log <- nested_log

if ("logrx Metadata" %in% names(nested_log)) {
parsed_log$`logrx Metadata` <-
nested_log$`logrx Metadata` %>%
unlist() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\: ",
into = c("Variable", "Value"),
extra = "merge"
)
}

if ("User and File Information" %in% names(nested_log)) {
parsed_log$`User and File Information` <-
nested_log$`User and File Information` %>%
unlist() %>%
stringr::str_trim() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\: ",
into = c("Variable", "Value")
)
}

if ("Session Information" %in% names(nested_log)) {
parsed_log$`Session Information`$`Session info` <-
nested_log$`Session Information`$`Session info` %>%
unlist() %>%
stringr::str_trim() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\s",
into = c("setting", "value"),
extra = "merge",
) %>%
dplyr::mutate(dplyr::across(dplyr::where(is.character), stringr::str_trim))

parsed_log$`Session Information`$`Packages` <-
nested_log$`Session Information`$`Packages` %>%
# remove indicator whether the package is attached to the search path
stringr::str_replace_all("\\*", " ") %>%
# account for loaded packages due to load_all()
stringr::str_replace_all(" P ", " ") %>%
readr::read_table(skip = 1, col_names = FALSE) %>%
dplyr::rename_with(~ c(
"package",
"version",
"date",
"lib",
"source",
"lang",
"r_version"
)) %>%
dplyr::mutate(
lang = stringr::str_remove(lang, "\\("),
r_version = stringr::str_remove(r_version, "\\)")
)

parsed_log$`Session Information`$`External software` <-
nested_log$`Session Information`$`External software` %>%
stringr::str_trim() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\s",
into = c("setting", "value"),
extra = "merge",
) %>%
dplyr::mutate(dplyr::across(dplyr::where(is.character), stringr::str_trim))
}

if ("Masked Functions" %in% names(nested_log)) {
parsed_log$`Masked Functions` <-
nested_log$`Masked Functions` %>%
unlist() %>%
tibble::tibble("Masked Functions" = .)
}

if ("Used Package and Functions" %in% names(nested_log)) {
parsed_log$`Used Package and Functions` <-
nested_log$`Used Package and Functions` %>%
unlist() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\} ",
into = c("library", "function_names")
) %>%
dplyr::mutate(library = stringr::str_remove(library, "\\{"))
}

if ("Program Run Time Information" %in% names(nested_log)) {
parsed_log$`Program Run Time Information` <-
nested_log$`Program Run Time Information` %>%
unlist() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\: ",
into = c("Variable", "Value")
)
}

if ("Log Output File" %in% names(nested_log)) {
parsed_log$`Log Output File` <-
nested_log$`Log Output File` %>%
unlist() %>%
tibble::tibble() %>%
tidyr::separate(".",
sep = "\\: ",
into = c("Variable", "Value")
)
}

return(parsed_log)
}

#' Read and parse previous logrx file
#'
#' @param file String. Path to a logrx log file
#'
#' @return Tibble. Object that includes nested and parsed content
#'
#' @examples
#' \dontrun{
#' read_log_file(previous_log_filepath)
#' }
#'
read_log_file <- function(file) {
if (!file.exists(file)) {
stop("Path does not exist:", sQuote(file))
}
con <- file(file.path(file), "r")
flines <- readLines(con)
close(con)

parsed_log <- flines %>%
reformat_subsections() %>%
nest_log() %>%
parse_log()
return(parsed_log)
}
4 changes: 4 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ reference:
- write_log_header
- write_unapproved_functions
- write_used_functions
- title: Read Previous Log
desc: Functionality to Read Previous Log Files
- contents:
- read_log_file
- title: Utilities
desc: Utility functions
- contents:
Expand Down
23 changes: 23 additions & 0 deletions man/read_log_file.Rd

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

Loading