关于 lifecycle
此技能帮助 R 包维护者依照 tidyverse 约定和 lifecycle 包管理函数及参数的生命周期。内容涵盖生命周期徽章、弃用与重命名模式、替代函数标记,以及弃用行为测试。
主要功能
- 01在 R 包中配置 lifecycle
- 02在文档中添加生命周期阶段徽章
- 03弃用或重命名函数及参数
- 04将函数标记为已替代或实验性
- 05测试弃用警告并抑制警告
适用场景
- 01为实验性函数编写文档
- 02提示用户使用重命名后的参数
- 03为主要版本安排弃用阶段
- 04测试已弃用函数的行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ posit-dev/ skills --skill lifecycle安装后在 Claude Code 中输入/lifecycle确认已加载。
附带文件references/lifecycle-stages.md
详细介绍
R 包生命周期管理
使用 tidyverse 约定和 lifecycle 包管理函数与参数的生命周期。
设置
检查 man/figures/ 中是否有 lifecycle-*.svg 文件,以确认是否已配置 lifecycle。
如果尚未配置,请运行:
usethis::use_lifecycle()
此操作将:
- 在 DESCRIPTION 的
Imports中添加 lifecycle - 在包文档文件中添加
@importFrom lifecycle deprecated - 将徽章 SVG 文件复制到
man/figures/
生命周期徽章
在 roxygen2 文档中插入徽章:
#' @description
#' `r lifecycle::badge("experimental")`
#' `r lifecycle::badge("deprecated")`
#' `r lifecycle::badge("superseded")`
对于参数:
#' @param old_arg `r lifecycle::badge("deprecated")` Use `new_arg` instead.
只有当函数或参数的阶段与包的整体阶段不同时,才添加徽章。
弃用函数
- 在
@description中添加徽章和说明:
#' Do something
#'
#' @description
#' `r lifecycle::badge("deprecated")`
#'
#' `old_fun()` was deprecated in mypkg 1.0.0. Use [new_fun()] instead.
#' @keywords internal
- 将
deprecate_warn()作为函数体的第一行添加:
old_fun <- function(x) {
lifecycle::deprecate_warn("1.0.0", "old_fun()", "new_fun()")
new_fun(x)
}
- 在示例中展示迁移方式:
#' @examples
#' old_fun(x)
#' # ->
#' new_fun(x)
弃用函数
| 函数 | 使用时机 |
|---|---|
deprecate_soft() | 第一阶段;仅向直接用户和测试期间发出警告 |
deprecate_warn() | 标准弃用;每 8 小时警告一次 |
deprecate_stop() | 移除前的最后阶段;报错并提供有用的消息 |
主要版本的弃用工作流:
- 搜索
deprecate_stop()——考虑彻底移除该函数 - 将
deprecate_warn()替换为deprecate_stop() - 将
deprecate_soft()替换为deprecate_warn()
重命名函数
将实现移至新名称,并在旧名称的函数中调用,同时添加弃用提示:
#' @description
#' `r lifecycle::badge("deprecated")`
#'
#' `add_two()` was renamed to `number_add()` for API consistency.
#' @keywords internal
#' @export
add_two <- function(x, y) {
lifecycle::deprecate_warn("1.0.0", "add_two()", "number_add()")
number_add(x, y)
}
#' Add two numbers
#' @export
number_add <- function(x, y) {
x + y
}
弃用参数
将 deprecated() 用作默认值,并使用 is_present() 检查:
#' @param path `r lifecycle::badge("deprecated")` Use `file` instead.
write_file <- function(x, file, path = deprecated()) {
if (lifecycle::is_present(path)) {
lifecycle::deprecate_warn("1.4.0", "write_file(path)", "write_file(file)")
file <- path
}
# ... rest of function
}
重命名参数
add_two <- function(x, y, na_rm = TRUE, na.rm = deprecated()) {
if (lifecycle::is_present(na.rm)) {
lifecycle::deprecate_warn("1.0.0", "add_two(na.rm)", "add_two(na_rm)")
na_rm <- na.rm
}
sum(x, y, na.rm = na_rm)
}
用其他函数取代某函数
对于有更好替代方案、但不应移除的函数:
#' Gather columns into key-value pairs
#'
#' @description
#' `r lifecycle::badge("superseded")`
#'
#' Development on `gather()` is complete. For new code, use [pivot_longer()].
#'
#' `df %>% gather("key", "value", x, y, z)` is equivalent to
#' `df %>% pivot_longer(c(x, y, z), names_to = "key", values_to = "value")`.
无需发出警告——只需记录推荐的替代方案。
标记为实验性
#' @description
#' `r lifecycle::badge("experimental")`
cool_function <- function() {
lifecycle::signal_stage("experimental", "cool_function()")
# ...
}
测试弃用
测试已弃用的函数能否正常运行并适时发出警告:
test_that("old_fun is deprecated", {
expect_snapshot({
x <- old_fun(1)
expect_equal(x, expected_value)
})
})
在现有测试中抑制警告:
test_that("old_fun returns correct value", {
withr::local_options(lifecycle_verbosity = "quiet")
expect_equal(old_fun(1), expected_value)
})
弃用辅助函数
对于影响多个函数的弃用(例如,移除一个通用参数),请创建内部辅助函数:
warn_for_verbose <- function(
verbose = TRUE,
env = rlang::caller_env(),
user_env = rlang::caller_env(2)
) {
if (!lifecycle::is_present(verbose) || isTRUE(verbose)) {
return(invisible())
}
lifecycle::deprecate_warn(
when = "2.0.0",
what = I("The `verbose` argument"),
details = c(
"Set `options(mypkg_quiet = TRUE)` to suppress messages.",
"The `verbose` argument will be removed in a future release."
),
user_env = user_env
)
invisible()
}
然后在受影响的函数中使用:
my_function <- function(..., verbose = deprecated()) {
warn_for_verbose(verbose)
# ...
}
自定义弃用消息
对于非标准弃用,使用 I() 包装自定义文本:
lifecycle::deprecate_warn(
when = "1.0.0",
what = I('Setting option "pkg.opt" to "foo"'),
with = I('"pkg.new_opt"')
)
what 片段必须能与追加的“was deprecated in...”搭配使用。
参考
请参阅 references/lifecycle-stages.md,了解详细的阶段定义和转换。
评论
支持 Markdown