From 6b858c688c1bbf98cc173a108a092adbd268c112 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 12:51:19 -0300 Subject: [PATCH 01/30] Prepare CRAN release v0.0.5 - Change maintainer to Tomasz Kalinowski (matching torch) - Bump version to 0.0.5 - Condition summary_audio example on wav availability - Add skip_if_not_installed("wav") to audio/read tests - Register internal as_tensor_proto S3 methods (roxygen2 7.3.3) - Add .claude to .Rbuildignore --- .Rbuildignore | 1 + DESCRIPTION | 7 ++++--- NAMESPACE | 4 ++++ NEWS.md | 4 +++- R/audio.R | 2 +- R/tensor.R | 4 ++++ man/summary_audio.Rd | 2 ++ tests/testthat/test-audio.R | 2 ++ tests/testthat/test-read.R | 1 + 9 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index e3d55ea..93068a5 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -36,3 +36,4 @@ ^cran-comments\.md$ ^CRAN-SUBMISSION$ ^configure\.log$ +^\.claude$ diff --git a/DESCRIPTION b/DESCRIPTION index 5c39c49..0d95da7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,9 @@ Package: tfevents Title: Write Events for 'TensorBoard' -Version: 0.0.4.9000 +Version: 0.0.5 Authors@R: c( - person("Daniel", "Falbel", email = "daniel@posit.co", role = c("aut", "cre", "cph")), + person("Daniel", "Falbel", email = "daniel@posit.co", role = c("aut", "cph")), + person("Tomasz", "Kalinowski", email = "tomasz@posit.co", role = c("cre")), person(family = "Posit, PBC", role = c("cph")), person(family = "The tl::optional authors", role = c("cph"), comment = "For the vendored tl::optional code."), person("Mark", "Adler", role = c("cph"), comment = "For the included crc32c code.") @@ -13,7 +14,7 @@ Description: Provides a convenient way to log scalars, images, audio, and histog License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.3 LinkingTo: Rcpp Imports: diff --git a/NAMESPACE b/NAMESPACE index 8fbee98..a95a22a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,6 +4,10 @@ S3method(as_event,character) S3method(as_event,list) S3method(as_event,numeric) S3method(as_event,tfevents_summary_values) +S3method(as_tensor_proto,array) +S3method(as_tensor_proto,blob) +S3method(as_tensor_proto,character) +S3method(as_tensor_proto,list) S3method(format,tfevents_event) S3method(format,tfevents_summary) S3method(format,tfevents_summary_values) diff --git a/NEWS.md b/NEWS.md index 53eeb9b..8e93f2c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,6 @@ -# tfevents (development version) +# tfevents 0.0.5 + +* Changed maintainer to Tomasz Kalinowski. # tfevents 0.0.4 diff --git a/R/audio.R b/R/audio.R index 815141c..8892634 100644 --- a/R/audio.R +++ b/R/audio.R @@ -7,7 +7,7 @@ #' @param sample_rate The sample rate in Hz associated to the audio values. #' @returns An audio summary that can be logged with [log_event()]. #' @family summary -#' @examples +#' @examplesIf rlang::is_installed("wav") #' tmp <- tempfile() #' with_logdir(tmp, { #' summary_audio(array(runif(100), dim = c(1,100, 1))) diff --git a/R/tensor.R b/R/tensor.R index ef6988a..25d1a67 100644 --- a/R/tensor.R +++ b/R/tensor.R @@ -15,6 +15,7 @@ as_tensor_proto <- function(x, dtype = NA, ...) { UseMethod("as_tensor_proto") } +#' @exportS3Method as_tensor_proto.blob <- function(x, dtype = NA, ...) { if (is.na(dtype)) dtype <- "string" if (!dtype %in% c("string")) @@ -22,6 +23,7 @@ as_tensor_proto.blob <- function(x, dtype = NA, ...) { tensor_proto(list(x), shape = new_tensor_shape(dim = length(x)), dtype = dtype) } +#' @exportS3Method as_tensor_proto.character <- function(x, dtype = NA, ...) { if (is.na(dtype)) dtype <- "string" if (!dtype %in% c("string")) @@ -29,6 +31,7 @@ as_tensor_proto.character <- function(x, dtype = NA, ...) { tensor_proto(list(x), shape = new_tensor_shape(dim = length(x)), dtype = dtype) } +#' @exportS3Method as_tensor_proto.array <- function(x, dtype = NA, ...) { dims <- dim(x) # proto store tensor data in C ordering, thus we need to reshape values @@ -37,6 +40,7 @@ as_tensor_proto.array <- function(x, dtype = NA, ...) { tensor_proto(x, shape = new_tensor_shape(dim = list(dims)), dtype = dtype) } +#' @exportS3Method as_tensor_proto.list <- function(x, dtype, ...) { c(x, dtype) %<-% vec_recycle_common(x, dtype) results <- lapply(seq_along(x), function(i) { diff --git a/man/summary_audio.Rd b/man/summary_audio.Rd index ddb5c87..f833da2 100644 --- a/man/summary_audio.Rd +++ b/man/summary_audio.Rd @@ -47,10 +47,12 @@ containing WAV encoded audio files. }} \examples{ +\dontshow{if (rlang::is_installed("wav")) withAutoprint(\{ # examplesIf} tmp <- tempfile() with_logdir(tmp, { summary_audio(array(runif(100), dim = c(1,100, 1))) }) +\dontshow{\}) # examplesIf} } \seealso{ Other summary: diff --git a/tests/testthat/test-audio.R b/tests/testthat/test-audio.R index 09d1ae2..75ba54e 100644 --- a/tests/testthat/test-audio.R +++ b/tests/testthat/test-audio.R @@ -1,4 +1,5 @@ test_that("can write an audio file", { + skip_if_not_installed("wav") f <- wav::read_wav(test_path("resources/test-audio.wav")) audio <- array(t(f), dim = c(1, rev(dim(f)))) @@ -21,6 +22,7 @@ test_that("can write an audio file", { }) test_that("can write multiple audio files from a array", { + skip_if_not_installed("wav") f <- wav::read_wav(test_path("resources/test-audio.wav")) f_t <- t(f) audio <- array(0, dim = c(10, rev(dim(f)))) diff --git a/tests/testthat/test-read.R b/tests/testthat/test-read.R index 0f9c83f..3f6f7d9 100644 --- a/tests/testthat/test-read.R +++ b/tests/testthat/test-read.R @@ -81,6 +81,7 @@ test_that("can iterate over events", { }) test_that("can extract value", { + skip_if_not_installed("wav") temp <- tempfile() From c5424a6d2e0963dcd7f6977f0fa353872f8fe873 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 13:07:44 -0300 Subject: [PATCH 02/30] Remove manual py_install step from pkgdown workflow Rely on reticulate's automatic Python dependency management via the tensorflow R package instead of manually installing. --- .github/workflows/pkgdown.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 1a405f6..66b4047 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -39,11 +39,6 @@ jobs: extra-packages: any::pkgdown, local::. needs: website - - name: Install Python deps - run: | - reticulate::py_install('tensorflow', pip = TRUE) - shell: Rscript {0} - - name: Build site run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} From cb023d9d9d19bdd28412e58587c36cbd5d40281c Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 13:42:41 -0300 Subject: [PATCH 03/30] Use py_require instead of manual py_install in CI Add py_require("tbparse") in test helper so reticulate handles installation automatically. Remove manual py_install steps from check and test-coverage workflows. --- .github/workflows/check.yaml | 6 ------ .github/workflows/test-coverage.yaml | 5 ----- tests/testthat/helper-tbparse.R | 2 ++ 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 3e1f161..78067ea 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -45,12 +45,6 @@ jobs: extra-packages: any::rcmdcheck needs: check - - name: Install Python libraries used for testing - continue-on-error: true - run: | - reticulate::py_install(c("tbparse", "tensorflow"), pip = TRUE) - shell: Rscript {0} - - uses: r-lib/actions/check-r-package@v2 with: upload-snapshots: true diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index 3aa3378..cddfc52 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -30,11 +30,6 @@ jobs: extra-packages: any::covr, any::xml2 needs: coverage - - name: Install Python libraries used for testing - run: | - reticulate::py_install(c("tbparse", "tensorflow"), pip = TRUE) - shell: Rscript {0} - - name: Test coverage run: | cov <- covr::package_coverage( diff --git a/tests/testthat/helper-tbparse.R b/tests/testthat/helper-tbparse.R index bd3127a..4f211d0 100644 --- a/tests/testthat/helper-tbparse.R +++ b/tests/testthat/helper-tbparse.R @@ -2,6 +2,8 @@ skip_if_tbparse_not_available <- function() { skip_if(inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) } +reticulate::py_require("tbparse") + if (inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) { tbparse <- NULL } else { From cfc5a30e3fbc3e9aa23b08ac1d278cbbff016d68 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 14:50:26 -0300 Subject: [PATCH 04/30] Also py_require tensorflow and tensorboard in test helper --- tests/testthat/helper-tbparse.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/helper-tbparse.R b/tests/testthat/helper-tbparse.R index 4f211d0..7ea5b75 100644 --- a/tests/testthat/helper-tbparse.R +++ b/tests/testthat/helper-tbparse.R @@ -2,7 +2,7 @@ skip_if_tbparse_not_available <- function() { skip_if(inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) } -reticulate::py_require("tbparse") +reticulate::py_require(c("tbparse", "tensorflow", "tensorboard")) if (inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) { tbparse <- NULL From 0794f5082c2b02de4ba236d039fbf4b3bf0d8737 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 14:59:18 -0300 Subject: [PATCH 05/30] Add py_require for tensorflow/tensorboard in hparams article --- vignettes/articles/hparams.Rmd | 1 + 1 file changed, 1 insertion(+) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 973cf2d..9d7be22 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,6 +11,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) +reticulate::py_require(c("tensorflow", "tensorboard")) ``` Hyperparameter tuning is a important step in machine learning problems. From f66b0be84332b24a56a5565ed07386cef7066312 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 15:07:37 -0300 Subject: [PATCH 06/30] Add reticulate Python bin dir to PATH for tensorboard CLI --- vignettes/articles/hparams.Rmd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 9d7be22..fc76b69 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -12,6 +12,9 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) reticulate::py_require(c("tensorflow", "tensorboard")) +# Ensure tensorboard CLI is on PATH +python_bin <- dirname(reticulate::py_config()$python) +Sys.setenv(PATH = paste(python_bin, Sys.getenv("PATH"), sep = ":")) ``` Hyperparameter tuning is a important step in machine learning problems. From 76e75bb73727c0696e0d22fef0512ef20a965d2f Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 15:26:55 -0300 Subject: [PATCH 07/30] Launch tensorboard using full path from Python env Resolve tensorboard binary from reticulate's Python bin directory instead of relying on PATH or tensorflow::tensorboard() which fails with newer tensorboard versions. --- vignettes/articles/hparams.Rmd | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index fc76b69..fe42f12 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -12,9 +12,6 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) reticulate::py_require(c("tensorflow", "tensorboard")) -# Ensure tensorboard CLI is on PATH -python_bin <- dirname(reticulate::py_config()$python) -Sys.setenv(PATH = paste(python_bin, Sys.getenv("PATH"), sep = ":")) ``` Hyperparameter tuning is a important step in machine learning problems. @@ -138,7 +135,13 @@ fs::dir_tree(temp) Finally, we can visualize the experiment results in TensorBoard: ```{r} -tensorflow::tensorboard(temp, port = 6060) +tensorboard <- file.path(dirname(reticulate::py_config()$python), "tensorboard") +p <- processx::process$new( + tensorboard, + c("--logdir", temp, "--host", "127.0.0.1", "--port", "6060"), + stdout = "|", stderr = "|" +) +Sys.sleep(5) ``` The screenshot below shows the table view in the HParams dashboard in TensorBoard. From 30916206bd215189ba86a5daa619ac83522dc5e4 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 15:49:21 -0300 Subject: [PATCH 08/30] Set CHROMOTE_CHROME env var for webshot2 in pkgdown workflow --- .github/workflows/pkgdown.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 66b4047..21686e6 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -21,6 +21,7 @@ jobs: group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + CHROMOTE_CHROME: google-chrome-stable permissions: contents: write steps: From e8815858f0af73eadc7e5284a4d9a7c100eec7a4 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Wed, 22 Apr 2026 15:58:46 -0300 Subject: [PATCH 09/30] Add tensorboard() function to tfevents Provides a working tensorboard launcher that finds the binary from reticulate's Python environment. Replaces tensorflow::tensorboard() calls in articles which broke with newer tensorboard versions. --- DESCRIPTION | 3 ++- NAMESPACE | 1 + NEWS.md | 1 + R/tensorboard.R | 37 ++++++++++++++++++++++++++++++++++ man/tensorboard.Rd | 21 +++++++++++++++++++ vignettes/articles/hparams.Rmd | 8 +------- vignettes/articles/images.Rmd | 7 ++++--- 7 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 R/tensorboard.R create mode 100644 man/tensorboard.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 0d95da7..c1d57fc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,7 +36,8 @@ Suggests: rmarkdown, ggplot2, tensorflow, - wav + wav, + processx SystemRequirements: libprotobuf, protobuf-compiler URL: https://github.com/mlverse/tfevents, https://mlverse.github.io/tfevents/ diff --git a/NAMESPACE b/NAMESPACE index a95a22a..48ccb56 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -72,6 +72,7 @@ export(summary_image) export(summary_metadata) export(summary_scalar) export(summary_text) +export(tensorboard) export(value) export(with_logdir) import(vctrs) diff --git a/NEWS.md b/NEWS.md index 8e93f2c..6465b8c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # tfevents 0.0.5 * Changed maintainer to Tomasz Kalinowski. +* Added `tensorboard()` function to launch TensorBoard from R. # tfevents 0.0.4 diff --git a/R/tensorboard.R b/R/tensorboard.R new file mode 100644 index 0000000..9640ba6 --- /dev/null +++ b/R/tensorboard.R @@ -0,0 +1,37 @@ +#' Launch TensorBoard +#' +#' Starts a TensorBoard server to visualize logged events. +#' +#' @param log_dir Path to the log directory. +#' @param host Host to bind TensorBoard to. Defaults to `"127.0.0.1"`. +#' @param port Port to bind TensorBoard to. Defaults to `6060`. +#' +#' @returns A [processx::process] object (invisibly). +#' @export +tensorboard <- function(log_dir, host = "127.0.0.1", port = 6060) { + rlang::check_installed("reticulate") + rlang::check_installed("processx") + + reticulate::py_require("tensorboard") + tb <- file.path(dirname(reticulate::py_config()$python), "tensorboard") + + if (!file.exists(tb)) { + cli::cli_abort("Unable to find the {.code tensorboard} binary at {.path {tb}}.") + } + + p <- processx::process$new( + tb, + c("--logdir", log_dir, "--host", host, "--port", as.character(port)), + stdout = "|", stderr = "|" + ) + + Sys.sleep(3) + if (!p$is_alive()) { + cli::cli_abort("Failed to launch TensorBoard.") + } + + url <- paste0("http://", host, ":", port) + cli::cli_inform("TensorBoard started at {.url {url}}") + + invisible(p) +} diff --git a/man/tensorboard.Rd b/man/tensorboard.Rd new file mode 100644 index 0000000..4971e17 --- /dev/null +++ b/man/tensorboard.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tensorboard.R +\name{tensorboard} +\alias{tensorboard} +\title{Launch TensorBoard} +\usage{ +tensorboard(log_dir, host = "127.0.0.1", port = 6060) +} +\arguments{ +\item{log_dir}{Path to the log directory.} + +\item{host}{Host to bind TensorBoard to. Defaults to \code{"127.0.0.1"}.} + +\item{port}{Port to bind TensorBoard to. Defaults to \code{6060}.} +} +\value{ +A \link[processx:process]{processx::process} object (invisibly). +} +\description{ +Starts a TensorBoard server to visualize logged events. +} diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index fe42f12..5f6e3fa 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -135,13 +135,7 @@ fs::dir_tree(temp) Finally, we can visualize the experiment results in TensorBoard: ```{r} -tensorboard <- file.path(dirname(reticulate::py_config()$python), "tensorboard") -p <- processx::process$new( - tensorboard, - c("--logdir", temp, "--host", "127.0.0.1", "--port", "6060"), - stdout = "|", stderr = "|" -) -Sys.sleep(5) +tensorboard(temp, port = 6060) ``` The screenshot below shows the table view in the HParams dashboard in TensorBoard. diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index 7906a1b..879d6c7 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,6 +16,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) +reticulate::py_require(c("tensorflow", "tensorboard")) ``` tfevents has the ability to write log images so they can be @@ -54,7 +55,7 @@ log_event("Training samples" = summary_image(train_imgs)) If we open the TensorBoard UI in the logdir we will see something like the below: ```{r} -tensorflow::tensorboard(normalizePath("logs"), port = 6060) +tensorboard(normalizePath("logs"), port = 6060) ``` Notice that images are also associated to a global step counter. If you save log @@ -89,7 +90,7 @@ log_event("Ggplot2 plot" = summary_image(p)) We now launch TensorBoard and see: ```{r} -tensorflow::tensorboard(temp, port = 6061) +tensorboard(temp, port = 6061) ``` ```{r ggpl, echo = FALSE, out.width="100%"} @@ -158,7 +159,7 @@ log_event("Raster plot" = summary_image(img)) It will be displayed in the dashboard: ```{r raster, echo = FALSE, out.width="100%"} -tensorflow::tensorboard(temp, port = 6062) +tensorboard(temp, port = 6062) webshot2::webshot("http://127.0.0.1:6062/?darkMode=false", vwidth = 1200) ``` From b6ea4fdfab22dbb29e9c0568503dd25d031da97d Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 09:56:46 -0300 Subject: [PATCH 10/30] Pin tensorflow<=2.18 in articles and add tensorboard to pkgdown index TF 2.21+ no longer installs the tensorboard CLI binary, so pin to <=2.18 where the binary is still available. --- _pkgdown.yml | 5 +++++ vignettes/articles/hparams.Rmd | 2 +- vignettes/articles/images.Rmd | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/_pkgdown.yml b/_pkgdown.yml index bb31b1c..d553a8e 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -24,6 +24,11 @@ reference: Related to logging hyperparameters contents: contains("hparams") + - title: TensorBoard + desc: > + Launch TensorBoard to visualize logged events + contents: + - tensorboard - title: Reading desc: > Related to reading tfevents record files diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 5f6e3fa..84ee67f 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,7 +11,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow", "tensorboard")) +reticulate::py_require(c("tensorflow<=2.18", "tensorboard")) ``` Hyperparameter tuning is a important step in machine learning problems. diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index 879d6c7..3da4081 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,7 +16,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow", "tensorboard")) +reticulate::py_require(c("tensorflow<=2.18", "tensorboard")) ``` tfevents has the ability to write log images so they can be From 5db8ae882b45f8815aeb42fc2e2ceeffa19bfec7 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 09:59:43 -0300 Subject: [PATCH 11/30] Use tensorflow::tensorboard() in articles with pinned tf version Revert the custom tensorboard() function. Instead, pin tensorflow<=2.18 and add setuptools to py_require so that tensorflow::tensorboard() works (newer TF drops the CLI binary, and tensorboard needs pkg_resources from setuptools). --- DESCRIPTION | 3 +-- NAMESPACE | 1 - NEWS.md | 1 - R/tensorboard.R | 37 ---------------------------------- _pkgdown.yml | 5 ----- man/tensorboard.Rd | 21 ------------------- vignettes/articles/hparams.Rmd | 5 +++-- vignettes/articles/images.Rmd | 9 +++++---- 8 files changed, 9 insertions(+), 73 deletions(-) delete mode 100644 R/tensorboard.R delete mode 100644 man/tensorboard.Rd diff --git a/DESCRIPTION b/DESCRIPTION index c1d57fc..0d95da7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,8 +36,7 @@ Suggests: rmarkdown, ggplot2, tensorflow, - wav, - processx + wav SystemRequirements: libprotobuf, protobuf-compiler URL: https://github.com/mlverse/tfevents, https://mlverse.github.io/tfevents/ diff --git a/NAMESPACE b/NAMESPACE index 48ccb56..a95a22a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -72,7 +72,6 @@ export(summary_image) export(summary_metadata) export(summary_scalar) export(summary_text) -export(tensorboard) export(value) export(with_logdir) import(vctrs) diff --git a/NEWS.md b/NEWS.md index 6465b8c..8e93f2c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,6 @@ # tfevents 0.0.5 * Changed maintainer to Tomasz Kalinowski. -* Added `tensorboard()` function to launch TensorBoard from R. # tfevents 0.0.4 diff --git a/R/tensorboard.R b/R/tensorboard.R deleted file mode 100644 index 9640ba6..0000000 --- a/R/tensorboard.R +++ /dev/null @@ -1,37 +0,0 @@ -#' Launch TensorBoard -#' -#' Starts a TensorBoard server to visualize logged events. -#' -#' @param log_dir Path to the log directory. -#' @param host Host to bind TensorBoard to. Defaults to `"127.0.0.1"`. -#' @param port Port to bind TensorBoard to. Defaults to `6060`. -#' -#' @returns A [processx::process] object (invisibly). -#' @export -tensorboard <- function(log_dir, host = "127.0.0.1", port = 6060) { - rlang::check_installed("reticulate") - rlang::check_installed("processx") - - reticulate::py_require("tensorboard") - tb <- file.path(dirname(reticulate::py_config()$python), "tensorboard") - - if (!file.exists(tb)) { - cli::cli_abort("Unable to find the {.code tensorboard} binary at {.path {tb}}.") - } - - p <- processx::process$new( - tb, - c("--logdir", log_dir, "--host", host, "--port", as.character(port)), - stdout = "|", stderr = "|" - ) - - Sys.sleep(3) - if (!p$is_alive()) { - cli::cli_abort("Failed to launch TensorBoard.") - } - - url <- paste0("http://", host, ":", port) - cli::cli_inform("TensorBoard started at {.url {url}}") - - invisible(p) -} diff --git a/_pkgdown.yml b/_pkgdown.yml index d553a8e..bb31b1c 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -24,11 +24,6 @@ reference: Related to logging hyperparameters contents: contains("hparams") - - title: TensorBoard - desc: > - Launch TensorBoard to visualize logged events - contents: - - tensorboard - title: Reading desc: > Related to reading tfevents record files diff --git a/man/tensorboard.Rd b/man/tensorboard.Rd deleted file mode 100644 index 4971e17..0000000 --- a/man/tensorboard.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tensorboard.R -\name{tensorboard} -\alias{tensorboard} -\title{Launch TensorBoard} -\usage{ -tensorboard(log_dir, host = "127.0.0.1", port = 6060) -} -\arguments{ -\item{log_dir}{Path to the log directory.} - -\item{host}{Host to bind TensorBoard to. Defaults to \code{"127.0.0.1"}.} - -\item{port}{Port to bind TensorBoard to. Defaults to \code{6060}.} -} -\value{ -A \link[processx:process]{processx::process} object (invisibly). -} -\description{ -Starts a TensorBoard server to visualize logged events. -} diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 84ee67f..04abc64 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,7 +11,8 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow<=2.18", "tensorboard")) +reticulate::py_require(c("tensorflow<=2.18", "tensorboard", "setuptools")) +Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` Hyperparameter tuning is a important step in machine learning problems. @@ -135,7 +136,7 @@ fs::dir_tree(temp) Finally, we can visualize the experiment results in TensorBoard: ```{r} -tensorboard(temp, port = 6060) +tensorflow::tensorboard(temp, port = 6060) ``` The screenshot below shows the table view in the HParams dashboard in TensorBoard. diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index 3da4081..b025d21 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,7 +16,8 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow<=2.18", "tensorboard")) +reticulate::py_require(c("tensorflow<=2.18", "tensorboard", "setuptools")) +Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` tfevents has the ability to write log images so they can be @@ -55,7 +56,7 @@ log_event("Training samples" = summary_image(train_imgs)) If we open the TensorBoard UI in the logdir we will see something like the below: ```{r} -tensorboard(normalizePath("logs"), port = 6060) +tensorflow::tensorboard(normalizePath("logs"), port = 6060) ``` Notice that images are also associated to a global step counter. If you save log @@ -90,7 +91,7 @@ log_event("Ggplot2 plot" = summary_image(p)) We now launch TensorBoard and see: ```{r} -tensorboard(temp, port = 6061) +tensorflow::tensorboard(temp, port = 6061) ``` ```{r ggpl, echo = FALSE, out.width="100%"} @@ -159,7 +160,7 @@ log_event("Raster plot" = summary_image(img)) It will be displayed in the dashboard: ```{r raster, echo = FALSE, out.width="100%"} -tensorboard(temp, port = 6062) +tensorflow::tensorboard(temp, port = 6062) webshot2::webshot("http://127.0.0.1:6062/?darkMode=false", vwidth = 1200) ``` From 9f106cdc618b08c80380ac76acf233dc2239d669 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 10:04:21 -0300 Subject: [PATCH 12/30] Pin tensorflow to 2.15.0 in articles --- vignettes/articles/hparams.Rmd | 2 +- vignettes/articles/images.Rmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 04abc64..feb1e35 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,7 +11,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow<=2.18", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index b025d21..9fcba17 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,7 +16,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) -reticulate::py_require(c("tensorflow<=2.18", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` From e8bec0b40925223b281c8f55389ce8c5ee8b3e2f Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 10:11:19 -0300 Subject: [PATCH 13/30] Require Python <=3.11 for tensorflow 2.15.0 compatibility --- vignettes/articles/hparams.Rmd | 1 + vignettes/articles/images.Rmd | 1 + 2 files changed, 2 insertions(+) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index feb1e35..9d55b64 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,6 +11,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) +reticulate::py_require(python = ">=3.9,<=3.11") reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index 9fcba17..5b5598b 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,6 +16,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) +reticulate::py_require(python = ">=3.9,<=3.11") reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` From 5d9db43f47c6263681a1cec6543fd04f6aae5fac Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 10:18:55 -0300 Subject: [PATCH 14/30] Pin tensorflow to 2.14.0 in articles --- vignettes/articles/hparams.Rmd | 2 +- vignettes/articles/images.Rmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index 9d55b64..b778ef8 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -12,7 +12,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index 5b5598b..e7a6fce 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -17,7 +17,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.15.0", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` From 339960836925945473361b5818fe1f27892a56da Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 10:48:52 -0300 Subject: [PATCH 15/30] Pin numpy<2 for tensorflow 2.14 compatibility --- vignettes/articles/hparams.Rmd | 2 +- vignettes/articles/images.Rmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index b778ef8..a0931d7 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -12,7 +12,7 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools", "numpy<2")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index e7a6fce..b658116 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -17,7 +17,7 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools")) +reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools", "numpy<2")) Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` From a1caa00b08afbe2df53986005892e021bda7e1af Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 10:59:50 -0300 Subject: [PATCH 16/30] Revert articles to original, restore py_install with pinned tf 2.14 Revert articles to use tensorflow::tensorboard() as-is. Restore py_install step in pkgdown workflow with tensorflow==2.14 and numpy<2 to ensure a proper pip environment where the tensorboard CLI works correctly. --- .github/workflows/pkgdown.yaml | 5 +++++ vignettes/articles/hparams.Rmd | 3 --- vignettes/articles/images.Rmd | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 21686e6..b27c5a1 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -40,6 +40,11 @@ jobs: extra-packages: any::pkgdown, local::. needs: website + - name: Install Python deps + run: | + reticulate::py_install(c('tensorflow==2.14', 'numpy<2'), pip = TRUE) + shell: Rscript {0} + - name: Build site run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} diff --git a/vignettes/articles/hparams.Rmd b/vignettes/articles/hparams.Rmd index a0931d7..973cf2d 100644 --- a/vignettes/articles/hparams.Rmd +++ b/vignettes/articles/hparams.Rmd @@ -11,9 +11,6 @@ knitr::opts_chunk$set( ```{r setup} library(tfevents) -reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools", "numpy<2")) -Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` Hyperparameter tuning is a important step in machine learning problems. diff --git a/vignettes/articles/images.Rmd b/vignettes/articles/images.Rmd index b658116..7906a1b 100644 --- a/vignettes/articles/images.Rmd +++ b/vignettes/articles/images.Rmd @@ -16,9 +16,6 @@ knitr::opts_knit$set(root.dir = temp) ```{r setup} library(tfevents) -reticulate::py_require(python = ">=3.9,<=3.11") -reticulate::py_require(c("tensorflow==2.14.0", "tensorboard", "setuptools", "numpy<2")) -Sys.setenv(PATH = paste(dirname(reticulate::py_config()$python), Sys.getenv("PATH"), sep = ":")) ``` tfevents has the ability to write log images so they can be From c1cb9631b81e3f55999ef368007d326f9bdb1561 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 11:08:09 -0300 Subject: [PATCH 17/30] Use python_version 3.11 in py_install for TF 2.14 compatibility --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index b27c5a1..0f569ac 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.14', 'numpy<2'), pip = TRUE) + reticulate::py_install(c('tensorflow==2.14', 'numpy<2'), pip = TRUE, python_version = '3.11') shell: Rscript {0} - name: Build site From 2ef447410df36e308b998d3a5f0b5f5833b9e247 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 11:18:24 -0300 Subject: [PATCH 18/30] Try tensorflow 2.13 in pkgdown workflow --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 0f569ac..b4b1ebb 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.14', 'numpy<2'), pip = TRUE, python_version = '3.11') + reticulate::py_install(c('tensorflow==2.13', 'numpy<2'), pip = TRUE, python_version = '3.11') shell: Rscript {0} - name: Build site From aa277d62f4e68b842a6bf2ce4db1fef03e6cdfde Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 11:37:43 -0300 Subject: [PATCH 19/30] Try tensorflow 2.10 in pkgdown workflow --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index b4b1ebb..0a3f2e1 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.13', 'numpy<2'), pip = TRUE, python_version = '3.11') + reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.11') shell: Rscript {0} - name: Build site From b75790ad942ae9d9c2cbad137d284bfc07847872 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 11:53:58 -0300 Subject: [PATCH 20/30] Use Python 3.9 for tensorflow 2.10 compatibility --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 0a3f2e1..7b66420 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.11') + reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.9') shell: Rscript {0} - name: Build site From 704e731812c2424ef7b0fa7c594dff0487401468 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 12:10:36 -0300 Subject: [PATCH 21/30] Use Python 3.10 for tensorflow 2.10 compatibility --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 7b66420..74c3fb7 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.9') + reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.10') shell: Rscript {0} - name: Build site From eaa885892290ac81982ae2f38392749255e41b4f Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Thu, 23 Apr 2026 14:20:31 -0300 Subject: [PATCH 22/30] Pin setuptools<70 to restore pkg_resources for tensorboard CLI --- .github/workflows/pkgdown.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 74c3fb7..4a9ff1e 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -42,7 +42,7 @@ jobs: - name: Install Python deps run: | - reticulate::py_install(c('tensorflow==2.10', 'numpy<2'), pip = TRUE, python_version = '3.10') + reticulate::py_install(c('tensorflow==2.10', 'numpy<2', 'setuptools<70'), pip = TRUE, python_version = '3.10') shell: Rscript {0} - name: Build site From bb6d3c1f7c7e4e73de838016d517a74e00a9218f Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Fri, 24 Apr 2026 11:25:48 -0300 Subject: [PATCH 23/30] Remove pragma diagnostic directives from generated protobuf headers --- configure | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/configure b/configure index c68582e..1bf5961 100755 --- a/configure +++ b/configure @@ -108,10 +108,9 @@ if [ ! -d "generated" ]; then 'protoc -I "proto" --cpp_out="generated" {}' \; fi -# copied from protolite: -# Suppress wanrings about pragmas in the autogenerated protobuf headers. -# Uwe + BDR have said this is OK and there is nothing we can do about this. -find ./ -type f -name "*.pb.h" -exec sed -i.bak "s@ #pragma@/*nowarn*/#pragma@g" {} \; +# Remove pragma diagnostic directives from autogenerated protobuf headers +# to avoid CRAN NOTEs about pragmas suppressing diagnostics. +find ./ -type f -name "*.pb.h" -exec sed -i.bak '/#pragma GCC diagnostic/d' {} \; PB_SRC=$(echo $(find generated -type f -name "*.pb.cc" -print)) CPP_SRC=$(echo $(find *.cpp -print)) From e77d55a0c734b3da7dd6bf934c46793a2e556b86 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Fri, 24 Apr 2026 11:29:04 -0300 Subject: [PATCH 24/30] Keep both pragma suppression approaches in configure --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 1bf5961..a2a2b81 100755 --- a/configure +++ b/configure @@ -110,6 +110,7 @@ fi # Remove pragma diagnostic directives from autogenerated protobuf headers # to avoid CRAN NOTEs about pragmas suppressing diagnostics. +find ./ -type f -name "*.pb.h" -exec sed -i.bak "s@ #pragma@/*nowarn*/#pragma@g" {} \; find ./ -type f -name "*.pb.h" -exec sed -i.bak '/#pragma GCC diagnostic/d' {} \; PB_SRC=$(echo $(find generated -type f -name "*.pb.cc" -print)) From 81c7790b339f43b31c6561d25537b5c67db2d190 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Fri, 24 Apr 2026 11:35:24 -0300 Subject: [PATCH 25/30] Suppress deprecated/nodiscard warnings from generated protobuf code Strip [[deprecated]] and [[nodiscard]] attributes from generated .pb.h/.pb.cc files in configure. Also fix nodiscard warning in reader.cpp by casting ParseFromString return value to void. --- configure | 7 +++++++ src/reader.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a2a2b81..207549e 100755 --- a/configure +++ b/configure @@ -113,6 +113,13 @@ fi find ./ -type f -name "*.pb.h" -exec sed -i.bak "s@ #pragma@/*nowarn*/#pragma@g" {} \; find ./ -type f -name "*.pb.h" -exec sed -i.bak '/#pragma GCC diagnostic/d' {} \; +# Strip [[deprecated]] and [[nodiscard]] attributes from generated protobuf +# code to avoid compilation warnings on CRAN. +find ./ -type f \( -name "*.pb.h" -o -name "*.pb.cc" \) -exec sed -i.bak \ + -e 's/\[\[deprecated\]\]//g' \ + -e 's/\[\[nodiscard\]\]//g' \ + -e 's/enum \(.*\) : int/enum \1 : int/' {} \; + PB_SRC=$(echo $(find generated -type f -name "*.pb.cc" -print)) CPP_SRC=$(echo $(find *.cpp -print)) CRC_SRC=$(echo $(find . -type f -name "*.c" -print)) diff --git a/src/reader.cpp b/src/reader.cpp index dbdfd94..cb8384c 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -45,7 +45,7 @@ tensorboard::Event EventFileIterator::get_next () { file.read(&buffer[0], length); tensorboard::Event event; - event.ParseFromString(std::string(buffer.begin(), buffer.end())); + (void)event.ParseFromString(std::string(buffer.begin(), buffer.end())); file.read(reinterpret_cast(&crc), sizeof(std::uint32_t)); From e44ec3ed624a50a86ad42a8780fda49c312cb45c Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Mon, 27 Apr 2026 08:01:52 -0300 Subject: [PATCH 26/30] Only py_require tbparse in test helper, not tensorflow Loading tensorflow during R CMD check creates ~/.keras/keras.json which violates CRAN policy. Tests only need tbparse. --- tests/testthat/helper-tbparse.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/helper-tbparse.R b/tests/testthat/helper-tbparse.R index 7ea5b75..4f211d0 100644 --- a/tests/testthat/helper-tbparse.R +++ b/tests/testthat/helper-tbparse.R @@ -2,7 +2,7 @@ skip_if_tbparse_not_available <- function() { skip_if(inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) } -reticulate::py_require(c("tbparse", "tensorflow", "tensorboard")) +reticulate::py_require("tbparse") if (inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) { tbparse <- NULL From 8735bf90094c0747ed5b6a3fe9027a03f484c96b Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Mon, 27 Apr 2026 08:02:42 -0300 Subject: [PATCH 27/30] Remove py_require from test helper to avoid side effects on CRAN --- tests/testthat/helper-tbparse.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/testthat/helper-tbparse.R b/tests/testthat/helper-tbparse.R index 4f211d0..bd3127a 100644 --- a/tests/testthat/helper-tbparse.R +++ b/tests/testthat/helper-tbparse.R @@ -2,8 +2,6 @@ skip_if_tbparse_not_available <- function() { skip_if(inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) } -reticulate::py_require("tbparse") - if (inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) { tbparse <- NULL } else { From 2544ee5cffd3cf00d1a48e5e572ec50cf3a34eb6 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Mon, 27 Apr 2026 08:23:19 -0300 Subject: [PATCH 28/30] Skip tensorflow-dependent test when not available, restore tbparse CI install - Add skip for tensorflow in test-image.R line 19 - Restore py_install('tbparse') in check and test-coverage workflows --- .github/workflows/check.yaml | 6 ++++++ .github/workflows/test-coverage.yaml | 5 +++++ tests/testthat/test-image.R | 2 ++ 3 files changed, 13 insertions(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 78067ea..ff05c01 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -45,6 +45,12 @@ jobs: extra-packages: any::rcmdcheck needs: check + - name: Install Python libraries used for testing + continue-on-error: true + run: | + reticulate::py_install('tbparse', pip = TRUE) + shell: Rscript {0} + - uses: r-lib/actions/check-r-package@v2 with: upload-snapshots: true diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index cddfc52..2dcfe24 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -30,6 +30,11 @@ jobs: extra-packages: any::covr, any::xml2 needs: coverage + - name: Install Python libraries used for testing + run: | + reticulate::py_install('tbparse', pip = TRUE) + shell: Rscript {0} + - name: Test coverage run: | cov <- covr::package_coverage( diff --git a/tests/testthat/test-image.R b/tests/testthat/test-image.R index 8534a26..141e028 100644 --- a/tests/testthat/test-image.R +++ b/tests/testthat/test-image.R @@ -12,6 +12,8 @@ test_that("write image", { skip_if_tbparse_not_available() + skip_if_not_installed("tensorflow") + skip_if(inherits(try(reticulate::import("tensorflow"), silent = TRUE), "try-error")) reader <- tbparse$SummaryReader(temp) buf <- reader$tensors$value[[1]][[3]] # TODO: in theory we don't need tensorflow for this, but couldnt find a way to From 8bf0e531375389bf01c96258ff3dd857de8218a2 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Mon, 27 Apr 2026 08:24:24 -0300 Subject: [PATCH 29/30] Also install tensorflow in check and test-coverage CI --- .github/workflows/check.yaml | 2 +- .github/workflows/test-coverage.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index ff05c01..ca3fb39 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -48,7 +48,7 @@ jobs: - name: Install Python libraries used for testing continue-on-error: true run: | - reticulate::py_install('tbparse', pip = TRUE) + reticulate::py_install(c('tbparse', 'tensorflow'), pip = TRUE) shell: Rscript {0} - uses: r-lib/actions/check-r-package@v2 diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index 2dcfe24..811487a 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -32,7 +32,7 @@ jobs: - name: Install Python libraries used for testing run: | - reticulate::py_install('tbparse', pip = TRUE) + reticulate::py_install(c('tbparse', 'tensorflow'), pip = TRUE) shell: Rscript {0} - name: Test coverage From fedc7a44a0e04289c5552c4f765e1e4de2401988 Mon Sep 17 00:00:00 2001 From: Daniel Falbel Date: Mon, 27 Apr 2026 08:25:53 -0300 Subject: [PATCH 30/30] Add skip_if_no_tensorflow helper that also skips on CRAN --- tests/testthat/helper-tbparse.R | 6 ++++++ tests/testthat/test-image.R | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/testthat/helper-tbparse.R b/tests/testthat/helper-tbparse.R index bd3127a..7ba9f0b 100644 --- a/tests/testthat/helper-tbparse.R +++ b/tests/testthat/helper-tbparse.R @@ -2,6 +2,12 @@ skip_if_tbparse_not_available <- function() { skip_if(inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) } +skip_if_no_tensorflow <- function() { + skip_on_cran() + skip_if_not_installed("tensorflow") + skip_if(inherits(try(reticulate::import("tensorflow"), silent = TRUE), "try-error")) +} + if (inherits(try(reticulate::import("tbparse"), silent = TRUE), "try-error")) { tbparse <- NULL } else { diff --git a/tests/testthat/test-image.R b/tests/testthat/test-image.R index 141e028..9eda47f 100644 --- a/tests/testthat/test-image.R +++ b/tests/testthat/test-image.R @@ -12,8 +12,7 @@ test_that("write image", { skip_if_tbparse_not_available() - skip_if_not_installed("tensorflow") - skip_if(inherits(try(reticulate::import("tensorflow"), silent = TRUE), "try-error")) + skip_if_no_tensorflow() reader <- tbparse$SummaryReader(temp) buf <- reader$tensors$value[[1]][[3]] # TODO: in theory we don't need tensorflow for this, but couldnt find a way to