Skip to content

Upkeep 2025 #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 26, 2025
Merged
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
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
^src/.*[.]gcno$
^dev-lib$
^vignettes$
^[\.]?air\.toml$
^\.vscode$
1 change: 0 additions & 1 deletion .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

name: R-CMD-check.yaml

Expand Down
1 change: 0 additions & 1 deletion .github/workflows/pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
release:
types: [published]
workflow_dispatch:
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/test-coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

name: test-coverage.yaml

Expand Down Expand Up @@ -35,14 +34,16 @@ jobs:
clean = FALSE,
install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
)
print(cov)
covr::to_cobertura(cov)
shell: Rscript {0}

- uses: codecov/codecov-action@v4
- uses: codecov/codecov-action@v5
with:
fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }}
file: ./cobertura.xml
plugin: noop
# Fail if error if not on PR, or if on PR and token is given
fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
files: ./cobertura.xml
plugins: noop
disable_search: true
token: ${{ secrets.CODECOV_TOKEN }}

Expand Down
5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"Posit.air-vscode"
]
}
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"[r]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "Posit.air-vscode"
}
}
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Authors@R: c(
person("Gábor", "Csárdi", , "csardi.gabor@gmail.com", role = c("aut", "cre", "cph"),
comment = c(ORCID = "0000-0001-7098-9676")),
person("Winston", "Chang", role = "aut"),
person("Posit Software, PBC", role = c("cph", "fnd")),
person("Posit Software, PBC", role = c("cph", "fnd"),
comment = c(ROR = "03wc8by49")),
person("Ascent Digital Services", role = c("cph", "fnd"))
)
Description: Tools to run system processes in the background. It can
Expand Down Expand Up @@ -38,6 +39,7 @@ Suggests:
withr
Config/Needs/website: tidyverse/tidytemplate
Config/testthat/edition: 3
Config/usethis/last-upkeep: 2025-04-25
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
YEAR: 2016-2024
YEAR: 2025
COPYRIGHT HOLDER: processx core team, see COPYRIGHTS file
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2023 processx authors
Copyright (c) 2025 processx authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
62 changes: 28 additions & 34 deletions R/aaa-import-standalone-rstudio-detect.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
# ---

rstudio <- local({

standalone_env <- environment()
parent.env(standalone_env) <- baseenv()

Expand All @@ -28,7 +27,8 @@ rstudio <- local({
"RSTUDIO_CONSOLE_COLOR",
"RSTUDIOAPI_IPC_REQUESTS_FILE",
"XPC_SERVICE_NAME",
"ASCIICAST")
"ASCIICAST"
)

d <- list(
pid = Sys.getpid(),
Expand Down Expand Up @@ -65,8 +65,10 @@ rstudio <- local({
if (clear_cache) data <<- NULL
if (!is.null(data)) return(get_caps(data))

if ((rspid <- Sys.getenv("RSTUDIO_SESSION_PID")) != "" &&
any(c("ps", "cli") %in% loadedNamespaces())) {
if (
(rspid <- Sys.getenv("RSTUDIO_SESSION_PID")) != "" &&
any(c("ps", "cli") %in% loadedNamespaces())
) {
detect_new(rspid, clear_cache)
} else {
detect_old(clear_cache)
Expand Down Expand Up @@ -99,31 +101,26 @@ rstudio <- local({

# direct subprocess
new$type <- if (rspid == parentpid) {

if (pane == "job") {
"rstudio_job"

} else if (pane == "build") {
"rstudio_build_pane"

} else if (pane == "render") {
"rstudio_render_pane"

} else if (pane == "terminal" && new$tty &&
new$envs["ASCIICAST"] != "true") {
} else if (
pane == "terminal" && new$tty && new$envs["ASCIICAST"] != "true"
) {
# not possible, because there is a shell in between, just in case
"rstudio_terminal"

} else {
# don't know what kind of direct subprocess
"rstudio_subprocess"
}

} else if (pane == "terminal" && new$tty &&
new$envs[["ASCIICAST"]] != "true") {
} else if (
pane == "terminal" && new$tty && new$envs[["ASCIICAST"]] != "true"
) {
# not a direct subproces, so check other criteria as well
"rstudio_terminal"

} else {
# don't know what kind of subprocess
"rstudio_subprocess"
Expand All @@ -133,58 +130,55 @@ rstudio <- local({
}

detect_old <- function(clear_cache = FALSE) {

# Cache unless told otherwise
cache <- TRUE
new <- get_data()

new$type <- if (new$envs[["RSTUDIO"]] != "1") {
# 1. Not RStudio at all
"not_rstudio"

} else if (new$gui == "RStudio" && new$api) {
# 2. RStudio console, properly initialized
"rstudio_console"

} else if (! new$api && basename(new$args[1]) == "RStudio") {
} else if (!new$api && basename(new$args[1]) == "RStudio") {
# 3. RStudio console, initializing
cache <- FALSE
"rstudio_console_starting"

} else if (new$gui == "Rgui") {
# Still not RStudio, but Rgui that was started from RStudio
"not_rstudio"

} else if (new$tty && new$envs[["ASCIICAST"]] != "true") {
# 4. R in the RStudio terminal
# This could also be a subprocess of the console or build pane
# with a pseudo-terminal. There isn't really a way to rule that
# out, without inspecting some process data with ps::ps_*().
# At least we rule out asciicast
"rstudio_terminal"

} else if (! new$tty &&
new$envs[["RSTUDIO_TERM"]] == "" &&
new$envs[["R_BROWSER"]] == "false" &&
new$envs[["R_PDFVIEWER"]] == "false" &&
is_build_pane_command(new$args)) {
} else if (
!new$tty &&
new$envs[["RSTUDIO_TERM"]] == "" &&
new$envs[["R_BROWSER"]] == "false" &&
new$envs[["R_PDFVIEWER"]] == "false" &&
is_build_pane_command(new$args)
) {
# 5. R in the RStudio build pane
# https://github.com/rstudio/rstudio/blob/master/src/cpp/session/
# modules/build/SessionBuild.cpp#L231-L240
"rstudio_build_pane"

} else if (new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
grepl("rstudio", new$envs[["XPC_SERVICE_NAME"]])) {
} else if (
new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
grepl("rstudio", new$envs[["XPC_SERVICE_NAME"]])
) {
# RStudio job, XPC_SERVICE_NAME=0 in the subprocess of a job
# process. Hopefully this is reliable.
"rstudio_job"

} else if (new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
any(grepl("SourceWithProgress.R", new$args))) {
} else if (
new$envs[["RSTUDIOAPI_IPC_REQUESTS_FILE"]] != "" &&
any(grepl("SourceWithProgress.R", new$args))
) {
# Or we can check SourceWithProgress.R in the command line, see
# https://github.com/r-lib/cli/issues/367
"rstudio_job"

} else {
# Otherwise it is a subprocess of the console, terminal or
# build pane, and it is hard to say which, so we do not try.
Expand Down
25 changes: 14 additions & 11 deletions R/aaassertthat.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@

assert_that <- function(..., env = parent.frame(), msg = NULL) {
res <- see_if(..., env = env, msg = msg)
if (res) return(TRUE)

throw(new_assert_error(attr(res, "msg")))
}

new_assert_error <- function (message, call = NULL) {
new_assert_error <- function(message, call = NULL) {
cond <- new_error(message, call. = call)
class(cond) <- c("assert_error", class(cond))
cond
Expand All @@ -16,17 +15,19 @@
asserts <- eval(substitute(alist(...)))

for (assertion in asserts) {
res <- tryCatch({
eval(assertion, env)
}, new_assert_error = function(e) {
structure(FALSE, msg = e$message)
})
res <- tryCatch(
{
eval(assertion, env)
},
new_assert_error = function(e) {
structure(FALSE, msg = e$message)

Check warning on line 23 in R/aaassertthat.R

View check run for this annotation

Codecov / codecov/patch

R/aaassertthat.R#L23

Added line #L23 was not covered by tests
}
)
check_result(res)

# Failed, so figure out message to produce
if (!res) {
if (is.null(msg))
msg <- get_message(res, assertion, env)
if (is.null(msg)) msg <- get_message(res, assertion, env)
return(structure(FALSE, msg = msg))
}
}
Expand All @@ -36,7 +37,9 @@

check_result <- function(x) {
if (!is.logical(x))
throw(new_assert_error("assert_that: assertion must return a logical value"))
throw(new_assert_error(
"assert_that: assertion must return a logical value"
))

Check warning on line 42 in R/aaassertthat.R

View check run for this annotation

Codecov / codecov/patch

R/aaassertthat.R#L40-L42

Added lines #L40 - L42 were not covered by tests
if (any(is.na(x)))
throw(new_assert_error("assert_that: missing values present in assertion"))
if (length(x) != 1) {
Expand Down Expand Up @@ -68,7 +71,7 @@
fail_default <- function(call, env) {
call_string <- deparse(call, width.cutoff = 60L)
if (length(call_string) > 1L) {
call_string <- paste0(call_string[1L], "...")
call_string <- paste0(call_string[1L], "...")

Check warning on line 74 in R/aaassertthat.R

View check run for this annotation

Codecov / codecov/patch

R/aaassertthat.R#L74

Added line #L74 was not covered by tests
}

paste0(call_string, " is not TRUE")
Expand Down
9 changes: 4 additions & 5 deletions R/assertions.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

is_string <- function(x) {
is.character(x) &&
length(x) == 1 &&
!is.na(x)
length(x) == 1 &&
!is.na(x)
}

on_failure(is_string) <- function(call, env) {
Expand All @@ -19,8 +18,8 @@ on_failure(is_string_or_null) <- function(call, env) {

is_flag <- function(x) {
is.logical(x) &&
length(x) == 1 &&
!is.na(x)
length(x) == 1 &&
!is.na(x)
}

on_failure(is_flag) <- function(call, env) {
Expand Down
1 change: 0 additions & 1 deletion R/base64.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

#' Base64 Encoding and Decoding
#'
#' @param x Raw vector to encode / decode.
Expand Down
1 change: 0 additions & 1 deletion R/cleancall.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

call_with_cleanup <- function(ptr, ...) {
.Call(c_cleancall_call, pairlist(ptr, ...), parent.frame())
}
8 changes: 3 additions & 5 deletions R/client-lib.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

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

local({
Expand Down Expand Up @@ -27,15 +26,13 @@ local({
# devtools
single <- system.file("src", paste0("client", ext), package = "processx")
client[[paste0("arch-", arch)]] <- read_all(single)

} else {
# not devtools
single <- file.path(libs, paste0("client", ext))
if (file.exists(single)) {
# not multiarch
bts <- file.size(single)
client[[paste0("arch-", arch)]] <- read_all(single)

} else {
# multiarch
multi <- dir(libs)
Expand All @@ -62,7 +59,7 @@ load_client_lib <- function(client) {
sym_encode <- getNativeSymbolInfo("processx_base64_encode", lib)
sym_decode <- getNativeSymbolInfo("processx_base64_decode", lib)
sym_disinh <- getNativeSymbolInfo("processx_disable_inheritance", lib)
sym_write <- getNativeSymbolInfo("processx_write", lib)
sym_write <- getNativeSymbolInfo("processx_write", lib)
sym_setout <- getNativeSymbolInfo("processx_set_stdout", lib)
sym_seterr <- getNativeSymbolInfo("processx_set_stderr", lib)
sym_setoutf <- getNativeSymbolInfo("processx_set_stdout_to_file", lib)
Expand Down Expand Up @@ -122,7 +119,8 @@ load_client_lib <- function(client) {
reg.finalizer(
env,
function(e) if (".finalize" %in% names(e)) e$.finalize(),
onexit = TRUE)
onexit = TRUE
)

## Clear the cleanup method
on.exit(NULL)
Expand Down
Loading