Repository: RMI-PACTA/workflow.pacta
Pull request #114: Explicit return for precheck & Linting 
Author: login: AlexAxthelm
Created: 2025-04-22T08:43:25Z | Merged: 2025-04-22T11:06:37Z

resolve some lintr lints that have popped up while I was out, preventing CI from running cleanly:

Functionality changes:
* `analysis_prechecks` now returns combined list from `calc_weights_prechecks` for both bonds and equity.

Linting:
* make `return` statements explicitly required (via `return_linter`)
* disable the `unneccesary_nesting_linter`
* suppress function calls in error messages


Diff:
diff --git a/.lintr b/.lintr
index 0e7510d..15124aa 100644
--- a/.lintr
+++ b/.lintr
@@ -1,4 +1,10 @@
-linters: all_linters()
+linters: all_linters(
+    return_linter = lintr::return_linter(
+      return_style = "explicit",
+      allow_implicit_else = FALSE
+    ),
+    unnecessary_nesting_linter = NULL
+  )
 exclusions: list(
     "tests/testthat.R"
   )
diff --git a/DESCRIPTION b/DESCRIPTION
index 1c314eb..2344d51 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: workflow.pacta
 Title: Run PACTA
-Version: 0.0.0.9015
+Version: 0.0.0.9016
 Authors@R: 
     c(person(given = "CJ",
              family = "Yetman",
diff --git a/R/calc_weights_and_outputs.R b/R/calc_weights_and_outputs.R
index 5471991..8b6633f 100644
--- a/R/calc_weights_and_outputs.R
+++ b/R/calc_weights_and_outputs.R
@@ -19,7 +19,7 @@
 #' @param start_year integer: Start year for analysis.
 #' @param time_horizon integer: Time horizon after start for analysis (usually
 #' 5 years).
-#' @return No return value. Saves outputs to output_dir.
+#' @return No return value (NULL). Saves outputs to output_dir.
 #' @export
 calc_weights_and_outputs <- function(
   total_portfolio,
@@ -198,6 +198,11 @@ calc_weights_and_outputs <- function(
         map,
         results_map_filename
       )
+    } else {
+      log_debug(
+        "No {portfolio_type} map data to save. ",
+        "Skipping {portfolio_type} map results."
+      )
     }
 
   } else {
@@ -207,6 +212,7 @@ calc_weights_and_outputs <- function(
     )
   }
 
+  return(NULL)
 }
 
 calc_weights_prechecks <- function(
@@ -223,7 +229,7 @@ calc_weights_prechecks <- function(
         nrow(total_portfolio) == 0L
     ) {
       log_error("Portfolio has no rows.")
-      stop("Portfolio has no rows.")
+      stop("Portfolio has no rows.", call. = FALSE)
     } else {
       log_trace("Portfolio has rows.")
     }
@@ -245,7 +251,7 @@ calc_weights_prechecks <- function(
       file.path(data_dir, "masterdata_debt_datastore.rds")
     )
   } else {
-    stop("Invalid portfolio type.")
+    stop("Invalid portfolio type.", call. = FALSE)
   }
   pacta.workflow.utils::check_io(
     input_files = input_files,
diff --git a/R/run_analysis.R b/R/run_analysis.R
index 980ac3a..f01dad3 100644
--- a/R/run_analysis.R
+++ b/R/run_analysis.R
@@ -15,7 +15,7 @@
 #' @param start_year integer: Start year for analysis.
 #' @param time_horizon integer: Time horizon after start for analysis (usually
 #' 5 years).
-#' @return No return value. Saves outputs to output_dir.
+#' @return No return value (NULL). Saves outputs to output_dir.
 #' @export
 run_analysis <- function(
   pacta_data_dir,
@@ -74,6 +74,7 @@ run_analysis <- function(
   )
 
   log_info("Finished PACTA calculations.")
+  return(NULL)
 }
 
 analysis_prechecks <- function(
@@ -96,18 +97,33 @@ analysis_prechecks <- function(
     log_trace("Skipping portfolio check.")
     total_portfolio <- data.frame()
   }
-  calc_weights_prechecks(
+  equity_prechecks <- calc_weights_prechecks(
     total_portfolio = total_portfolio,
     portfolio_type = "Equity",
     output_dir = output_dir,
     data_dir = pacta_data_dir,
     check_portfolio = check_portfolio
   )
-  calc_weights_prechecks(
+  bonds_prechecks <- calc_weights_prechecks(
     total_portfolio = total_portfolio,
     portfolio_type = "Bonds",
     output_dir = output_dir,
     data_dir = pacta_data_dir,
     check_portfolio = check_portfolio
   )
+  prechecks <- list(
+    input_files = unique(
+      c(
+        equity_prechecks$input_files,
+        bonds_prechecks$input_files
+      )
+    ),
+    output_dir = unique(
+      c(
+        equity_prechecks$output_dir,
+        bonds_prechecks$output_dir
+      )
+    )
+  )
+  return(prechecks)
 }
diff --git a/R/run_pacta.R b/R/run_pacta.R
index ce6a36a..7eb5cf1 100644
--- a/R/run_pacta.R
+++ b/R/run_pacta.R
@@ -36,15 +36,15 @@ run_pacta <- function(
   log_debug("Checking configuration.")
   if (is.null(pacta_data_dir) || pacta_data_dir == "") {
     log_error("PACTA_DATA_DIR not set.")
-    stop("PACTA_DATA_DIR not set.")
+    stop("PACTA_DATA_DIR not set.", call. = FALSE)
   }
   if (is.null(output_dir) || output_dir == "") {
     log_error("ANALYSIS_OUTPUT_DIR not set.")
-    stop("ANALYSIS_OUTPUT_DIR not set.")
+    stop("ANALYSIS_OUTPUT_DIR not set.", call. = FALSE)
   }
   if (is.null(portfolio_dir) || portfolio_dir == "") {
     log_error("PORTFOLIO_DIR not set.")
-    stop("PORTFOLIO_DIR not set.")
+    stop("PORTFOLIO_DIR not set.", call. = FALSE)
   }
   log_info("Running PACTA")
 
diff --git a/inst/extdata/scripts/run_pacta.R b/inst/extdata/scripts/run_pacta.R
index eea32e2..f7fd6fb 100644
--- a/inst/extdata/scripts/run_pacta.R
+++ b/inst/extdata/scripts/run_pacta.R
@@ -5,7 +5,7 @@ if (
     Sys.getenv("ANALYSIS_OUTPUT_DIR") == ""
 ) {
   log_error("ANALYSIS_OUTPUT_DIR not set.")
-  stop("ANALYSIS_OUTPUT_DIR not set.")
+  stop("ANALYSIS_OUTPUT_DIR not set.", call. = FALSE)
 }
 
 raw_params <- commandArgs(trailingOnly = TRUE)
diff --git a/man/calc_weights_and_outputs.Rd b/man/calc_weights_and_outputs.Rd
index 03e4a40..638aac1 100644
--- a/man/calc_weights_and_outputs.Rd
+++ b/man/calc_weights_and_outputs.Rd
@@ -45,7 +45,7 @@ in the scenario data.}
 5 years).}
 }
 \value{
-No return value. Saves outputs to output_dir.
+No return value (NULL). Saves outputs to output_dir.
 }
 \description{
 This function calculates the weights and outputs for the
diff --git a/man/run_analysis.Rd b/man/run_analysis.Rd
index 602611d..fc7ad35 100644
--- a/man/run_analysis.Rd
+++ b/man/run_analysis.Rd
@@ -38,7 +38,7 @@ in the scenario data.}
 5 years).}
 }
 \value{
-No return value. Saves outputs to output_dir.
+No return value (NULL). Saves outputs to output_dir.
 }
 \description{
 This function runs the PACTA analysis for a portfolio.
diff --git a/tests/testthat/test-analysis_prechecks.R b/tests/testthat/test-analysis_prechecks.R
index 150afd5..5f74cb7 100644
--- a/tests/testthat/test-analysis_prechecks.R
+++ b/tests/testthat/test-analysis_prechecks.R
@@ -69,6 +69,7 @@ test_that("audit_prechecks fails when total_portfolio.rds missing", {
     regexp = "^IO checks failed.$"
   )
 })
+
 test_that("analysis_prechecks passes port missing, check_portfolio is FALSE", {
   pacta_data_dir <- withr::local_tempdir()
   filenames <- c(
@@ -96,6 +97,8 @@ test_that("analysis_prechecks passes port missing, check_portfolio is FALSE", {
     object = results,
     expected = list(
       input_files = c(
+        file.path(pacta_data_dir, "equity_abcd_scenario.rds"),
+        file.path(pacta_data_dir, "masterdata_ownership_datastore.rds"),
         file.path(pacta_data_dir, "bonds_abcd_scenario.rds"),
         file.path(pacta_data_dir, "masterdata_debt_datastore.rds")
       ),


Reviews:
user: login: cjyetman
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-22T10:26:50Z
user: login: cjyetman
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-22T10:28:34Z
user: login: AlexAxthelm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-22T11:06:34Z

Review comments:
diff_hunk: @@ -207,6 +212,7 @@ calc_weights_and_outputs <- function(
     )
   }
 
+  return(NULL)
path: R/calc_weights_and_outputs.R
user: login: cjyetman
body: While I prefer explicitly returning whatever like this, linters (following tidyverse style) usually tell you to just pass the object
created_at: 2025-04-22T10:26:50Z
author_association: MEMBER
diff_hunk: @@ -207,6 +212,7 @@ calc_weights_and_outputs <- function(
     )
   }
 
+  return(NULL)
path: R/calc_weights_and_outputs.R
user: login: AlexAxthelm
body: Yeah, checking for explicit return is one of the changes in the `.lintr` file I made for this repo. 
created_at: 2025-04-22T11:06:34Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-22T08:45:04Z
body: # Docker build status
| commit_time | git_sha | image |
| --- | --- | --- |
| 2025-04-22T10:07:59Z | cc49257c2b6db1dcc91f24e23b27af28ed931e66 | ghcr.io/rmi-pacta/workflow.pacta:pr-114 |
author_association: NONE
user: login: cjyetman
created_at: 2025-04-22T09:29:28Z
body: assuming you want to deal with the failing test before I review?
author_association: MEMBER
user: login: codecov[bot]
created_at: 2025-04-22T10:10:19Z
body: ## [Codecov](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) Report
Attention: Patch coverage is `64.28571%` with `10 lines` in your changes missing coverage. Please review.
> Project coverage is 20.44%. Comparing base [(`77c9e49`)](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/commit/77c9e49c94e770684d66e247972665dedfc3e770?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) to head [(`cc49257`)](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/commit/cc49257c2b6db1dcc91f24e23b27af28ed931e66?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA).
> Report is 1 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) | Patch % | Lines |
|---|---|---|
| [R/calc\_weights\_and\_outputs.R](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&filepath=R%2Fcalc_weights_and_outputs.R&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA#diff-Ui9jYWxjX3dlaWdodHNfYW5kX291dHB1dHMuUg==) | 14.28% | [6 Missing :warning: ](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) |
| [R/run\_pacta.R](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&filepath=R%2Frun_pacta.R&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA#diff-Ui9ydW5fcGFjdGEuUg==) | 0.00% | [3 Missing :warning: ](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) |
| [R/run\_analysis.R](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&filepath=R%2Frun_analysis.R&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA#diff-Ui9ydW5fYW5hbHlzaXMuUg==) | 94.44% | [1 Missing :warning: ](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #114      +/-   ##
==========================================
+ Coverage   17.92%   20.44%   +2.52%     
==========================================
  Files           4        4              
  Lines         424      445      +21     
==========================================
+ Hits           76       91      +15     
- Misses        348      354       +6     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/RMI-PACTA/workflow.pacta/pull/114?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RMI-PACTA).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: AlexAxthelm
created_at: 2025-04-22T10:20:47Z
body: Thanks @cjyetman Bit out of practice with waiting for checks to run before requesting.
author_association: CONTRIBUTOR