mcpField
R
r-lifecycle

r-lifecycle

github.com/posit-dev开发55178 次安装今天更新
代码仓库

关于 r-lifecycle

为 R 包开发者提供按 tidyverse 约定管理函数和参数生命周期的技能,涵盖实验、弃用与替代阶段的标记、警告及测试。

主要功能

  1. 01设置 lifecycle 支持
  2. 02添加生命周期徽章
  3. 03弃用或重命名函数与参数
  4. 04管理实验和 superseded 阶段
  5. 05测试弃用行为

适用场景

  1. 01为 R 函数标记弃用并提示替代项
  2. 02在多个版本中逐步推进弃用流程
  3. 03为参数重命名保留兼容性
  4. 04验证弃用警告及相关测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posit-dev/skills --skill r-lifecycle

安装后在 Claude Code 中输入/r-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.

只有当函数或参数的阶段与包的整体阶段不同时,才添加徽章。

弃用函数

  1. 在 @description 中添加徽章和说明:
#' Do something
#'
#' @description
#' `r lifecycle::badge("deprecated")`
#'
#' `old_fun()` was deprecated in mypkg 1.0.0. Use [new_fun()] instead.
#' @keywords internal
  1. 将 deprecate_warn() 作为函数体的第一行添加:
old_fun <- function(x) {

lifecycle::deprecate_warn("1.0.0", "old_fun()", "new_fun()")
new_fun(x)
}
  1. 在示例中展示迁移方式:
#' @examples
#' old_fun(x)
#' # ->
#' new_fun(x)

弃用函数

函数使用时机
deprecate_soft()第一阶段;仅向直接用户和测试期间发出警告
deprecate_warn()标准弃用;每 8 小时警告一次
deprecate_stop()移除前的最后阶段;报错并提供有用的消息

主要版本的弃用工作流:

  1. 搜索 deprecate_stop()——考虑彻底移除该函数
  2. 将 deprecate_warn() 替换为 deprecate_stop()
  3. 将 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