Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
infotroph authored Dec 13, 2024
2 parents 6f2ab9f + cab30e8 commit 07ec3d3
Show file tree
Hide file tree
Showing 141 changed files with 1,143 additions and 1,256 deletions.
3 changes: 3 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My change requires a change to the documentation.
- [ ] My name is in the list of CITATION.cff
- [ ] I agree that PEcAn Project may distribute my contribution under any or all of
- the same license as the existing code,
- and/or the BSD 3-clause license.
- [ ] I have updated the CHANGELOG.md.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the **CONTRIBUTING** document.
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ jobs:
stale:
if: github.repository == 'PecanProject/pecan'

permissions:
contents: write
issues: write
pull-requests: write

runs-on: ubuntu-latest

steps:
- uses: actions/stale@v6
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 365 days with no activity.'
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ For more information about this file see also [Keep a Changelog](http://keepacha
* Model packages `PEcAn.BASGRA`, `PEcAn.CLM45`, `PEcAn.DALEC`, `PEcAn.dvmdostem`, `PEcAn.FATES`, `PEcAn.GDAY`, `PEcAn.JULES`, `PEcAn.LDNDC`, `PEcAn.LINKAGES`, `PEcAn.LPJGUESS`, `PEcAn.MAAT`, `PEcAn.MAESPA`, `PEcAn.PRELES`, `PEcAn.SIBCASA`, `PEcAn.SIPNET`, `PEcAn.STICS`, and the new model package template.
* Modules `PEcAn.allometry`, `PEcAn.assim.batch`, `PEcAn.data.mining`, `PEcAn.emulator`, `PEcAn.MA`, `PEcAn.photosynthesis`, `PEcAn.priors`, and `PEcAn.RTM`.
- Renamed master branch to main
- `PEcAn.all::pecan_version()` now reports commit hashes as well as version numbers for each installed package.

### Removed

Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ git push -u origin GH-issuenumber-title-of-issue

When finished create a pull request from your branch to the main pecan repository.

When submitting a pull request, you retain authorship of the code you contribute. However, you are giving the PEcAn Project permission to distribute your contributions under either or both, at our discretion, of:
- The license listed at PR opening time for the code you are contributing to,
- and/or the BSD 3-clause license.

## Additional Resources

- [Adding models to PEcAn](https://pecanproject.github.io/pecan-documentation/latest/adding-an-ecosystem-model.html)
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,19 @@ drop_parents = $(filter-out $(patsubst %/,%,$(dir $1)), $1)
# Generates a list of regular files at any depth inside its argument
files_in_dir = $(call drop_parents, $(call recurse_dir, $1))

# Git hash + clean status for this directory
git_rev = $(shell \
CLEAN=$$([[ -n $$(git status -s $1) ]] && echo "+mod"); \
echo $$(git rev-parse --short=10 HEAD)"$$CLEAN")

# HACK: NA vs TRUE switch on dependencies argument is an ugly workaround for
# a circular dependency between benchmark and data.land.
# When this is fixed, can go back to simple `dependencies = TRUE`
depends_R_pkg = ./scripts/time.sh "depends ${1}" ./scripts/confirm_deps.R ${1} \
$(if $(findstring modules/benchmark,$(1)),NA,TRUE)
install_R_pkg = ./scripts/time.sh "install ${1}" Rscript \
-e ${SETROPTIONS} \
-e "Sys.setenv(PECAN_GIT_REV='$(call git_rev,$1)')" \
-e "remotes::install_local('$(strip $(1))', force=TRUE, dependencies=FALSE, upgrade=FALSE)"
check_R_pkg = ./scripts/time.sh "check ${1}" Rscript scripts/check_with_errors.R $(strip $(1))
test_R_pkg = ./scripts/time.sh "test ${1}" Rscript \
Expand Down
1 change: 1 addition & 0 deletions base/all/NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Generated by roxygen2: do not edit by hand

S3method(print,pecan_version_report)
export(pecan_version)
4 changes: 4 additions & 0 deletions base/all/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
## License change
* PEcAn.all is now distributed under the BSD three-clause license instead of the NCSA Open Source license.

## Changed
* `pecan_version()` now reports the Git revision (if known) for each package,
and prints its results more compactly for easier reading.

# PEcAn.all 1.8.0

## Added
Expand Down
61 changes: 55 additions & 6 deletions base/all/R/pecan_version.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
#' @param exact Show only tags that exactly match `version`,
#' or all tags that have it as a substring?
#' @return data frame with columns for package name, expected version(s),
#' and installed version.
#' If the `sessioninfo` package is installed, a fourth column reports where
#' each package was installed from: local, github, CRAN, etc.
#' installed version, and Git hash (if known).
#' If the `sessioninfo` package is installed, an additional column reports
#' where each package was installed from: local, github, CRAN, etc.
#'
#' @examples
#' pecan_version()
Expand All @@ -46,7 +46,7 @@ pecan_version <- function(version = max(PEcAn.all::pecan_releases$version),
)
version <- unique(unlist(version))
}
cols_to_return <- c("package", version, "installed")
cols_to_return <- c("package", version, "installed", "build_hash")


if (requireNamespace("sessioninfo", quietly = TRUE)) {
Expand Down Expand Up @@ -94,14 +94,20 @@ pecan_version <- function(version = max(PEcAn.all::pecan_releases$version),
our_pkgs <- our_pkgs[!duplicated(our_pkgs),]
}

want_hash <- !is.na(our_pkgs$installed)
our_pkgs$build_hash[want_hash] <- sapply(
our_pkgs$package[want_hash],
get_buildhash)

res <- merge(
x = our_pkgs,
y = PEcAn.all::pecan_version_history,
all = TRUE)
res <- res[, cols_to_return]
res <- drop_na_version_rows(res[, cols_to_return])
rownames(res) <- res$package
class(res) <- c("pecan_version_report", class(res))

drop_na_version_rows(res)
res
}

# Remove rows where all versions are missing
Expand All @@ -110,3 +116,46 @@ drop_na_version_rows <- function(df) {
stopifnot(colnames(df)[[1]] == "package")
df[rowSums(is.na(df[, -1])) < ncol(df[, -1]), ]
}


# Look up git revision, if recorded, from an installed PEcAn package
get_buildhash <- function(pkg) {
# Set if pkg was installed from r-universe or via install_github()
desc_sha <- utils::packageDescription(pkg, fields = "RemoteSha")
if (!is.na(desc_sha)) {
return(substr(desc_sha, 1, 10))
}
# Set if PECAN_GIT_REV was set during install (includes `make install`)
get0(".build_hash", envir = asNamespace(pkg), ifnotfound = NA_character_)
}


# print method for version
# (Just to help it display more compactly)
#' @export
print.pecan_version_report <- function(x, ...) {

dots <- list(...)
if (is.null(dots$row.names)) { dots$row.names <- FALSE }
if (is.null(dots$right)) { dots$right <- FALSE }

xx <- as.data.frame(x)
# only print hash for dev versions
# (typically x.y.z.9000, but we'll use anything with a 4th version component)
skip_hash <- is.na(xx$installed[,4]) | is.na(xx$build_hash)
xx$build_hash[skip_hash] <- ""
xx$build_hash <- sub(".{4}\\+mod$", "+mod", xx$build_hash)
xx$installed <- paste0(
xx$installed,
sub("(.+)", " (\\1)", xx$build_hash))
xx$build_hash <- NULL
if (!is.null(xx$source)) {
xx$source <- paste0(
strtrim(xx$source, 17),
ifelse(nchar(xx$source, type="width") <= 17, "", "..."))
}
dots$x <- xx
do.call("print", dots)

invisible(x)
}
3 changes: 3 additions & 0 deletions base/all/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
52 changes: 28 additions & 24 deletions base/all/data/pecan_version_history.R
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@

# Read and format a list of pecan versions

pecan_version_history <- utils::read.csv(
"pecan_version_history.csv",
colClasses = "character",
check.names = FALSE)
# The local() wrapper is to avoid adding objects to the package data:
# Any extra vars defined at the top level of this file would be loaded
# into the global environment by `data("pecan_version_history")`

# We'd like to parse strictly to catch invalid versions (probably typos).
# But we _need_ to allow NAs... and in R < 4.4, package_version did not
# accept NAs unless strict=FALSE.
strict <- TRUE
na_version <- try(
package_version(NA_character_, strict = strict),
silent = TRUE)
if (inherits(na_version, "try-error")) {
strict <- FALSE
}
pecan_version_history <- local({
pvh <- utils::read.csv(
"pecan_version_history.csv",
colClasses = "character",
check.names = FALSE)

for (col in colnames(pecan_version_history)) {
if (col != "package") {
pecan_version_history[[col]] <- package_version(
pecan_version_history[[col]],
strict = strict)
# We'd like to parse strictly to catch invalid versions (probably typos).
# But we _need_ to allow NAs... and in R < 4.4, package_version did not
# accept NAs unless strict=FALSE.
strict <- TRUE
na_version <- try(
package_version(NA_character_, strict = strict),
silent = TRUE)
if (inherits(na_version, "try-error")) {
strict <- FALSE
}
}

# Now remove local vars
# Yes, this really is needed: _all_ objects left defined at end of script
# will be added to the package data list!
rm(strict, na_version, col)
for (col in colnames(pvh)) {
if (col != "package") {
pvh[[col]] <- package_version(
pvh[[col]],
strict = strict)
}
}

pvh
})
6 changes: 3 additions & 3 deletions base/all/man/pecan_version.Rd

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

46 changes: 40 additions & 6 deletions base/all/tests/testthat/test-pecan_version.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ test_that("pecan_version", {
# tags substring matched only when exact = FALSE
expect_named(
pecan_version("v1.5"),
c("package", paste0("v1.5.", 0:3), "installed", "source")
c("package", paste0("v1.5.", 0:3), "installed", "build_hash", "source")
)
expect_error(
pecan_version("v1.5", exact = TRUE),
"undefined columns"
)
expect_named(
pecan_version("v1.3", exact = TRUE),
c("package", "v1.3", "installed", "source")
c("package", "v1.3", "installed", "build_hash", "source")
)

# returns current release if no args given
noargs <- pecan_version()
expected_tag <- tail(PEcAn.all::pecan_releases, 1)$tag
expect_length(noargs, 4)
expect_named(noargs, c("package", expected_tag, "installed", "source"))
expect_length(noargs, 5)
expect_named(noargs, c("package", expected_tag, "installed", "build_hash", "source"))

# Why the `any()`s below?
# Because R CMD check runs tests with local test dir added to .libPaths,
Expand Down Expand Up @@ -77,8 +77,8 @@ test_that("pecan_version without sessioninfo", {
mockery::stub(pecan_version, 'requireNamespace', FALSE)
without_sessinfo <- pecan_version()

expect_length(with_sessinfo, 4)
expect_length(without_sessinfo, 3)
expect_length(with_sessinfo, 5)
expect_length(without_sessinfo, 4)
expect_equal(
with_sessinfo[, colnames(with_sessinfo) != "source"],
without_sessinfo)
Expand All @@ -91,3 +91,37 @@ test_that("pecan_version without sessioninfo", {
# The approach that failed just before I wrote this note:
# No, the version of PEcAn.all (1.8.1.9000 today) is not reliably in sync with
# the PEcAn version last tagged as a release (1.7.2 today).


test_that("printing", {
ver <- structure(
data.frame(
package = "PEcAnFake",
v0.0 = package_version("1.2.3"),
installed = package_version("1.2.3.9000"),
build_hash = "01234567ab",
source = "13 characters"),
class = c("pecan_version_report", "data.frame")
)

long_ver <- ver
long_ver$build_hash = "01234567ab+mod"
long_ver$source = "twenty-two characters"

# hash truncated to fit "+mod" if present
expect_output(print(ver), "01234567ab", fixed = TRUE)
expect_output(print(long_ver), "012345+mod", fixed = TRUE)

# source truncated to total of 20 chars
expect_output(print(ver), "13 characters$")
expect_output(print(long_ver), "twenty-two charac...", fixed = TRUE)

# source truncation works on width not glyph count
long_ver$source <- gsub("tw", "\U{1F197}\U{1F192}", long_ver$source)
expect_output(print(long_ver), "\U{1F192}o ch...", fixed = TRUE)

# dots passed on
expect_output(print(ver), "\n PEcAnFake")
expect_output(print(ver, row.names = TRUE), "\n1 PEcAnFake", fixed = TRUE)
expect_output(print(ver, quote = TRUE), "\n \"PEcAnFake\"", fixed = TRUE)
})
2 changes: 1 addition & 1 deletion base/db/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Suggests:
tidyverse,
withr
License: BSD_3_clause + file LICENSE
VignetteBuilder: knitr
VignetteBuilder: knitr, rmarkdown
Copyright: Authors
LazyLoad: yes
LazyData: FALSE
Expand Down
3 changes: 3 additions & 0 deletions base/db/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
3 changes: 3 additions & 0 deletions base/logger/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
2 changes: 1 addition & 1 deletion base/qaqc/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ Copyright: Authors
LazyLoad: yes
LazyData: FALSE
Encoding: UTF-8
VignetteBuilder: knitr
VignetteBuilder: knitr, rmarkdown
Config/testthat/edition: 3
RoxygenNote: 7.3.2
3 changes: 3 additions & 0 deletions base/qaqc/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
3 changes: 3 additions & 0 deletions base/remote/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
3 changes: 3 additions & 0 deletions base/settings/R/version.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Set at package install time, used by pecan.all::pecan_version()
# to identify development versions of packages
.build_hash <- Sys.getenv("PECAN_GIT_REV", "unknown")
32 changes: 3 additions & 29 deletions base/utils/LICENSE
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
University of Illinois/NCSA Open Source License

Copyright (c) 2012, University of Illinois, NCSA. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimers.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
- Neither the names of University of Illinois, NCSA, nor the names
of its contributors may be used to endorse or promote products
derived from this Software without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.

YEAR: 2024
COPYRIGHT HOLDER: PEcAn Project
ORGANIZATION: PEcAn Project, authors affiliations
Loading

0 comments on commit 07ec3d3

Please sign in to comment.