Skip to content
Closed
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
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ Collate:
'coord-transform.R'
'data.R'
'docs_layer.R'
'edition.R'
'facet-.R'
'facet-grid-.R'
'facet-null.R'
Expand Down
73 changes: 73 additions & 0 deletions R/edition.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

ggplot_edition <- new.env(parent = emptyenv())

local_edition <- function(edition, .env = parent.frame()) {
stopifnot(is_zap(edition) || (is.numeric(edition) && length(edition) == 1))
pkg <- get_pkg_name(.env)
local_bindings(!!pkg := edition, .env = ggplot_edition, .frame = .env)
}

edition_get <- function(.env = parent.frame(), default = 2024L) {
pkg <- get_pkg_name(.env)

# Try to query edition from cache
edition <- env_get(ggplot_edition, nm = pkg, default = NULL)
if (!is.null(edition)) {
return(edition)
}

# Try to query package description
desc_file <- find_description(path = ".", package = pkg)
if (is.null(desc_file)) {
return(default)
}

# Look up edition from the description
field_name <- "Config/ggplot2/edition"
edition <- as.integer(read.dcf(desc_file, fields = field_name))

# Cache result
env_bind(ggplot_edition, !!pkg := edition)
return(edition)
}

edition_deprecate <- function(edition, ..., .env = parent.frame()) {
check_number_whole(edition)
if (edition_get(.env) < edition) {
return(invisible(NULL))
}

edition <- I(paste0("edition ", edition))
lifecycle::deprecate_stop(edition, ...)
}

edition_require <- function(edition, what, .env = parent.frame()) {
check_number_whole(edition)
current <- edition_get(.env)
if (current >= edition) {
return(invisible(NULL))
}
msg <- paste0(what, " requires the ", edition, " edition of {.pkg ggplot2}.")
cli::cli_abort(msg)
}

find_description <- function(path, package = NULL) {
if (!is.null(package)) {
path <- system.file(package = package, "DESCRIPTION")
} else {
path <- file.path(path, "DESCRIPTION")
}
if (!file.exists(path)) {
return(NULL)
}
path
}

get_pkg_name <- function(env = parent.frame()) {
env <- topenv(env)
name <- environmentName(env)
if (!isNamespace(env) && name != "R_GlobalEnv") {
return(NULL)
}
name
}
16 changes: 16 additions & 0 deletions tests/testthat/_snaps/edition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# basic edition infrastructure works as intended

Code
edition_deprecate(2025, what = "foo()")
Condition
Error:
! `foo()` was deprecated in ggplot2 edition 2025 and is now defunct.

---

Code
edition_require(2025, what = "foo()")
Condition
Error in `edition_require()`:
! foo() requires the 2025 edition of ggplot2.

10 changes: 10 additions & 0 deletions tests/testthat/test-edition.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
test_that("basic edition requirement and deprecation works as intended", {

local_edition(2025)
expect_snapshot(edition_deprecate(2025, what = "foo()"), error = TRUE)
expect_silent(edition_require(2025, what = "foo()"))

local_edition(2024)
expect_silent(edition_deprecate(2025, what = "foo()"))
expect_snapshot(edition_require(2025, what = "foo()"), error = TRUE)
})