From 10d8600fae421da67755f4b1cf95543ff4b8fd4a Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:10:04 +0200 Subject: [PATCH 01/11] Create package docs and centralise imports. --- R/blob-package.R | 7 +++++++ R/blob.R | 5 ----- man/blob-package.Rd | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 R/blob-package.R create mode 100644 man/blob-package.Rd diff --git a/R/blob-package.R b/R/blob-package.R new file mode 100644 index 0000000..da575b9 --- /dev/null +++ b/R/blob-package.R @@ -0,0 +1,7 @@ +#' @keywords internal +"_PACKAGE" + +#' @import vctrs +#' @import rlang +#' @importFrom methods setOldClass +NULL diff --git a/R/blob.R b/R/blob.R index 9146f23..cfcd271 100644 --- a/R/blob.R +++ b/R/blob.R @@ -1,8 +1,3 @@ -#' @import vctrs -#' @import rlang -NULL - -#' @importFrom methods setOldClass setOldClass(c("blob", "vctrs_list_of", "vctrs_vctr")) #' Construct a blob object diff --git a/man/blob-package.Rd b/man/blob-package.Rd new file mode 100644 index 0000000..340bd16 --- /dev/null +++ b/man/blob-package.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/blob-package.R +\docType{package} +\name{blob-package} +\alias{blob-package} +\title{blob: A Simple S3 Class for Representing Vectors of Binary Data ('BLOBS')} +\description{ +R's raw vector is useful for storing a single binary object. What if you want to put a vector of them in a data frame? The 'blob' package provides the blob object, a list of raw vectors, suitable for use as a column in data frame. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://blob.tidyverse.org} + \item \url{https://github.com/tidyverse/blob} + \item Report bugs at \url{https://github.com/tidyverse/blob/issues} +} + +} +\author{ +\strong{Maintainer}: Kirill Müller \email{kirill@cynkra.com} + +Authors: +\itemize{ + \item Hadley Wickham +} + +Other contributors: +\itemize{ + \item RStudio [copyright holder, funder] +} + +} +\keyword{internal} From 7d0a02760d167a5f18056a5169c0e7405f642caa Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:23:51 +0200 Subject: [PATCH 02/11] Bump to testhat 3 --- DESCRIPTION | 3 ++- tests/testthat.R | 8 ++++++++ tests/testthat/test-accessors.R | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ebd1c69..197b712 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,10 +21,11 @@ Suggests: covr, crayon, pillar (>= 1.2.1), - testthat + testthat (>= 3.0.0) Config/autostyle/scope: line_breaks Config/autostyle/strict: false Config/Needs/website: tidyverse/tidytemplate Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.2.9000 +Config/testthat/edition: 3 diff --git a/tests/testthat.R b/tests/testthat.R index 1137369..36b5a22 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,3 +1,11 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + library(testthat) library(blob) diff --git a/tests/testthat/test-accessors.R b/tests/testthat/test-accessors.R index eb314a0..ac887f6 100644 --- a/tests/testthat/test-accessors.R +++ b/tests/testthat/test-accessors.R @@ -24,8 +24,8 @@ test_that("subset assignment works", { test_that("can't insert objects of incorrect type", { x <- blob(!!!as.raw(1:5)) - expect_error(x[[1]] <- 1, class = "vctrs_error_incompatible", fixed = TRUE) - expect_error(x[1] <- 1, class = "vctrs_error_incompatible", fixed = TRUE) + expect_error(x[[1]] <- 1, regexp = "Can't convert `value` to ", class = "vctrs_error_incompatible", fixed = TRUE) + expect_error(x[1] <- 1, regexp = "Can't convert `X[[i]]` to ", class = "vctrs_error_incompatible", fixed = TRUE) }) test_that("can insert raw or NULL", { From 5f7117da492c75bd58bcf66970471b6e939aa5ef Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:30:10 +0200 Subject: [PATCH 03/11] devtools() -> pak() --- README.Rmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.Rmd b/README.Rmd index e25593e..4757525 100644 --- a/README.Rmd +++ b/README.Rmd @@ -39,8 +39,8 @@ install.packages("tidyverse") install.packages("blob") # Or the the development version from GitHub: -# install.packages("devtools") -devtools::install_github("tidyverse/blob") +# install.packages("pak") +pak::pak("tidyverse/blob") ``` ## Example From a9b6872195ae570ff8b77cf12a7e2af64f1d3366 Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:31:24 +0200 Subject: [PATCH 04/11] Remove downlit dependency and use standard rendering. --- README.Rmd | 2 +- README.md | 76 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/README.Rmd b/README.Rmd index 4757525..55afcd3 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,5 +1,5 @@ --- -output: downlit::readme_document +output: github_document --- diff --git a/README.md b/README.md index c3ed857..51a74e5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ - -[![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) [![rcc](https://github.com/tidyverse/blob/workflows/rcc/badge.svg)](https://github.com/tidyverse/blob/actions) [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/blob)](https://cran.r-project.org/package=blob) [![Coverage Status](https://codecov.io/gh/tidyverse/blob/branch/main/graph/badge.svg)](https://app.codecov.io/gh/tidyverse/blob) + +[![Lifecycle: +stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) +[![rcc](https://github.com/tidyverse/blob/workflows/rcc/badge.svg)](https://github.com/tidyverse/blob/actions) +[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/blob)](https://cran.r-project.org/package=blob) +[![Coverage +Status](https://codecov.io/gh/tidyverse/blob/branch/main/graph/badge.svg)](https://app.codecov.io/gh/tidyverse/blob) @@ -10,44 +15,53 @@ ## Overview -The goal of blob is to provide a simple S3 class to represent a vector of binary objects, aka blobs. The `blob` class is a lightweight wrapper around a list of raw vectors, suitable for inclusion in a data frame. +The goal of blob is to provide a simple S3 class to represent a vector +of binary objects, aka blobs. The `blob` class is a lightweight wrapper +around a list of raw vectors, suitable for inclusion in a data frame. -In most cases you will not need to use this package explicitly: it will be used transparently by packages that need to load BLOB columns from databases or binary file formats. +In most cases you will not need to use this package explicitly: it will +be used transparently by packages that need to load BLOB columns from +databases or binary file formats. ## Installation -
-# The easiest way to get blob is to install the whole tidyverse:
-install.packages("tidyverse")
-
-# Alternatively, install just blob:
-install.packages("blob")
-
-# Or the the development version from GitHub:
-# install.packages("devtools")
-devtools::install_github("tidyverse/blob")
+``` r +# The easiest way to get blob is to install the whole tidyverse: +install.packages("tidyverse") + +# Alternatively, install just blob: +install.packages("blob") + +# Or the the development version from GitHub: +# install.packages("pak") +pak::pak("tidyverse/blob") +``` ## Example To create a blob, use `blob()`, `new_blob()` or `as_blob()`: -
-library(blob)
-
-x1 <- charToRaw("Good morning")
-x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f))
-
-new_blob(list(x1, x2))
-#> <blob[2]>
-#> [1] blob[12 B] blob[5 B]
-blob(x1, x2)
-#> <blob[2]>
-#> [1] blob[12 B] blob[5 B]
-
-as_blob(c("Good morning", "Good evening"))
-#> <blob[2]>
-#> [1] blob[12 B] blob[12 B]
+``` r +library(blob) + +x1 <- charToRaw("Good morning") +x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f)) + +new_blob(list(x1, x2)) +#> +#> [1] blob[12 B] blob[5 B] +blob(x1, x2) +#> +#> [1] blob[12 B] blob[5 B] + +as_blob(c("Good morning", "Good evening")) +#> +#> [1] blob[12 B] blob[12 B] +``` ------------------------------------------------------------------------ -Please note that the ‘blob’ project is released with a [Contributor Code of Conduct](https://github.com/tidyverse/blob/blob/main/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. +Please note that the ‘blob’ project is released with a [Contributor Code +of +Conduct](https://github.com/tidyverse/blob/blob/main/CODE_OF_CONDUCT.md). +By contributing to this project, you agree to abide by its terms. From 2f6aef51c06310f9c1d1986b0eb7e47e98385c23 Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:32:23 +0200 Subject: [PATCH 05/11] Tidy description with usethis::use_tidy_description() --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 197b712..8231234 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -25,7 +25,7 @@ Suggests: Config/autostyle/scope: line_breaks Config/autostyle/strict: false Config/Needs/website: tidyverse/tidytemplate +Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.2.9000 -Config/testthat/edition: 3 From e79aa0964087c223fe2cecf85fff0451d7a02b83 Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:35:17 +0200 Subject: [PATCH 06/11] Use air --- .Rbuildignore | 2 ++ .vscode/extensions.json | 5 +++++ .vscode/settings.json | 6 ++++++ air.toml | 0 4 files changed, 13 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 air.toml diff --git a/.Rbuildignore b/.Rbuildignore index d6a2cb3..073da7e 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -16,3 +16,5 @@ ^CRAN-RELEASE$ ^\.github$ ^LICENSE\.md$ +^[\.]?air\.toml$ +^\.vscode$ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..344f76e --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "Posit.air-vscode" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f2d0b79 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[r]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "Posit.air-vscode" + } +} diff --git a/air.toml b/air.toml new file mode 100644 index 0000000..e69de29 From 378b24d08189f6eb1fc00bc6faeb507128cab89a Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:38:48 +0200 Subject: [PATCH 07/11] Format package w/ air --- R/cast.R | 4 +++- R/coerce.R | 4 +++- R/compat-lifecycle.R | 41 +++++++++++++++++++-------------- R/format.R | 12 +++++++--- R/util.R | 6 +++-- tests/testthat/test-accessors.R | 14 +++++++++-- tests/testthat/test-cast.R | 10 ++++++-- 7 files changed, 63 insertions(+), 28 deletions(-) diff --git a/R/cast.R b/R/cast.R index 8fe391d..ec91324 100644 --- a/R/cast.R +++ b/R/cast.R @@ -31,7 +31,9 @@ vec_cast.blob.vctrs_list_of <- function(x, to, ...) { #' @method vec_cast.blob integer #' @export vec_cast.blob.integer <- function(x, to, ...) { - signal_soft_deprecated("Coercing an integer vector to a blob is deprecated, please coerce to a list first.") + signal_soft_deprecated( + "Coercing an integer vector to a blob is deprecated, please coerce to a list first." + ) blob(!!!lapply(x, as_single_raw)) } diff --git a/R/coerce.R b/R/coerce.R index b762e8b..f29754e 100644 --- a/R/coerce.R +++ b/R/coerce.R @@ -7,7 +7,9 @@ #' @method vec_ptype2 blob #' @export #' @export vec_ptype2.blob -vec_ptype2.blob <- function(x, y, ..., x_arg = "", y_arg = "") UseMethod("vec_ptype2.blob", y) +vec_ptype2.blob <- function(x, y, ..., x_arg = "", y_arg = "") { + UseMethod("vec_ptype2.blob", y) +} #' @method vec_ptype2.blob default #' @export diff --git a/R/compat-lifecycle.R b/R/compat-lifecycle.R index d1e5b28..657834f 100644 --- a/R/compat-lifecycle.R +++ b/R/compat-lifecycle.R @@ -25,7 +25,6 @@ # # - Soft-namespaced private objects. - #' Signal deprecation #' #' @description @@ -99,8 +98,10 @@ signal_soft_deprecated <- function(msg, id = msg, env = rlang::caller_env(2)) { rlang::is_reference(topenv(env), rlang::global_env()) } - if (rlang::is_true(rlang::peek_option("lifecycle_verbose_soft_deprecation")) || - env_inherits_global(env)) { + if ( + rlang::is_true(rlang::peek_option("lifecycle_verbose_soft_deprecation")) || + env_inherits_global(env) + ) { warn_deprecated(msg, id) return(invisible(NULL)) } @@ -108,9 +109,12 @@ signal_soft_deprecated <- function(msg, id = msg, env = rlang::caller_env(2)) { # Test for environment names rather than reference/contents because # testthat clones the namespace tested_package <- Sys.getenv("TESTTHAT_PKG") - if (nzchar(tested_package) && - identical(Sys.getenv("NOT_CRAN"), "true") && - rlang::env_name(topenv(env)) == rlang::env_name(rlang::ns_env(tested_package))) { + if ( + nzchar(tested_package) && + identical(Sys.getenv("NOT_CRAN"), "true") && + rlang::env_name(topenv(env)) == + rlang::env_name(rlang::ns_env(tested_package)) + ) { warn_deprecated(msg, id) return(invisible(NULL)) } @@ -126,12 +130,14 @@ warn_deprecated <- function(msg, id = msg) { return(invisible(NULL)) } - if (!rlang::is_true(rlang::peek_option("lifecycle_repeat_warnings")) && - rlang::env_has(.rlang_lifecycle_deprecation_env, id)) { + if ( + !rlang::is_true(rlang::peek_option("lifecycle_repeat_warnings")) && + rlang::env_has(.rlang_lifecycle_deprecation_env, id) + ) { return(invisible(NULL)) } - rlang::env_poke(.rlang_lifecycle_deprecation_env, id, TRUE); + rlang::env_poke(.rlang_lifecycle_deprecation_env, id, TRUE) has_colour <- function() rlang::is_installed("crayon") && crayon::has_color() silver <- function(x) if (has_colour()) crayon::silver(x) else x @@ -143,7 +149,11 @@ warn_deprecated <- function(msg, id = msg) { } if (!rlang::is_true(rlang::peek_option("lifecycle_repeat_warnings"))) { - msg <- paste0(msg, "\n", silver("This warning is displayed once per session.")) + msg <- paste0( + msg, + "\n", + silver("This warning is displayed once per session.") + ) } .Signal(msg = msg) @@ -163,9 +173,7 @@ stop_defunct <- function(msg) { } local_lifecycle_silence <- function(frame = rlang::caller_env()) { - rlang::local_options(.frame = frame, - lifecycle_disable_warnings = TRUE - ) + rlang::local_options(.frame = frame, lifecycle_disable_warnings = TRUE) } with_lifecycle_silence <- function(expr) { local_lifecycle_silence() @@ -173,7 +181,8 @@ with_lifecycle_silence <- function(expr) { } local_lifecycle_warnings <- function(frame = rlang::caller_env()) { - rlang::local_options(.frame = frame, + rlang::local_options( + .frame = frame, lifecycle_disable_warnings = FALSE, lifecycle_verbose_soft_deprecation = TRUE, lifecycle_repeat_warnings = TRUE @@ -186,9 +195,7 @@ with_lifecycle_warnings <- function(expr) { local_lifecycle_errors <- function(frame = rlang::caller_env()) { local_lifecycle_warnings(frame = frame) - rlang::local_options(.frame = frame, - lifecycle_warnings_as_errors = TRUE - ) + rlang::local_options(.frame = frame, lifecycle_warnings_as_errors = TRUE) } with_lifecycle_errors <- function(expr) { local_lifecycle_errors() diff --git a/R/format.R b/R/format.R index 84ff7f6..031ab41 100644 --- a/R/format.R +++ b/R/format.R @@ -1,15 +1,17 @@ #' @export format.blob <- function(x, ...) { - if (length(x) == 0) + if (length(x) == 0) { return(character()) + } ifelse(is.na(x), "", paste0("blob[", blob_size(x, ...), "]")) } #' @export obj_print_data.blob <- function(x, ...) { - if (length(x) == 0) + if (length(x) == 0) { return() + } out <- stats::setNames(format(x), names(x)) print(out, quote = FALSE) @@ -41,7 +43,11 @@ pillar_shaft.blob <- function(x, ...) { out <- ifelse( is.na(x), NA_character_, - paste0(pillar::style_subtle("")) + paste0( + pillar::style_subtle("") + ) ) pillar::new_pillar_shaft_simple(out, align = "right") diff --git a/R/util.R b/R/util.R index 673aaac..f49cd34 100644 --- a/R/util.R +++ b/R/util.R @@ -1,12 +1,14 @@ is_raw_list <- function(x) { - if (!is.list(x)) + if (!is.list(x)) { return(FALSE) + } raw <- vapply(x, is.raw, logical(1)) null <- vapply(x, is.null, logical(1)) - if (!all(raw | null)) + if (!all(raw | null)) { return(FALSE) + } TRUE } diff --git a/tests/testthat/test-accessors.R b/tests/testthat/test-accessors.R index ac887f6..a2988b8 100644 --- a/tests/testthat/test-accessors.R +++ b/tests/testthat/test-accessors.R @@ -24,8 +24,18 @@ test_that("subset assignment works", { test_that("can't insert objects of incorrect type", { x <- blob(!!!as.raw(1:5)) - expect_error(x[[1]] <- 1, regexp = "Can't convert `value` to ", class = "vctrs_error_incompatible", fixed = TRUE) - expect_error(x[1] <- 1, regexp = "Can't convert `X[[i]]` to ", class = "vctrs_error_incompatible", fixed = TRUE) + expect_error( + x[[1]] <- 1, + regexp = "Can't convert `value` to ", + class = "vctrs_error_incompatible", + fixed = TRUE + ) + expect_error( + x[1] <- 1, + regexp = "Can't convert `X[[i]]` to ", + class = "vctrs_error_incompatible", + fixed = TRUE + ) }) test_that("can insert raw or NULL", { diff --git a/tests/testthat/test-cast.R b/tests/testthat/test-cast.R index 4d6eb89..d327f74 100644 --- a/tests/testthat/test-cast.R +++ b/tests/testthat/test-cast.R @@ -8,7 +8,10 @@ test_that("casting with as.blob()", { expect_identical(as.blob(list(raw(1))), blob(raw(1))) expect_identical(as.blob(raw(1)), blob(raw(1))) expect_identical(as.blob(1:3), blob(as.raw(1), as.raw(2), as.raw(3))) - expect_identical(as.blob(c("abc", "def")), blob(charToRaw("abc"), charToRaw("def"))) + expect_identical( + as.blob(c("abc", "def")), + blob(charToRaw("abc"), charToRaw("def")) + ) }) test_that("casting with as_blob()", { @@ -16,7 +19,10 @@ test_that("casting with as_blob()", { expect_identical(as_blob(list(raw(1))), blob(raw(1))) expect_identical(as_blob(raw(1)), blob(raw(1))) expect_identical(blob(!!!as.raw(1:3)), blob(as.raw(1), as.raw(2), as.raw(3))) - expect_identical(as_blob(c("abc", "def")), blob(charToRaw("abc"), charToRaw("def"))) + expect_identical( + as_blob(c("abc", "def")), + blob(charToRaw("abc"), charToRaw("def")) + ) }) test_that("NA_character_ is converted to missing blob()", { From 016b865f2463ddd1a53429af96bf5687b3328cd7 Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:42:00 +0200 Subject: [PATCH 08/11] Remove superseeded context() calls --- tests/testthat/test-accessors.R | 2 -- tests/testthat/test-cast.R | 2 -- tests/testthat/test-construction.R | 2 -- tests/testthat/test-format.R | 2 -- tests/testthat/test-missing.R | 2 -- 5 files changed, 10 deletions(-) diff --git a/tests/testthat/test-accessors.R b/tests/testthat/test-accessors.R index a2988b8..022eebc 100644 --- a/tests/testthat/test-accessors.R +++ b/tests/testthat/test-accessors.R @@ -1,5 +1,3 @@ -context("accessors") - test_that("subsetting blob returns blob", { x <- blob(!!!as.raw(1:5)) expect_s3_class(x[1], "blob") diff --git a/tests/testthat/test-cast.R b/tests/testthat/test-cast.R index d327f74..18668fa 100644 --- a/tests/testthat/test-cast.R +++ b/tests/testthat/test-cast.R @@ -1,5 +1,3 @@ -context("test-cast") - test_that("casting with as.blob()", { # Deprecated in v1.2.0 local_lifecycle_silence() diff --git a/tests/testthat/test-construction.R b/tests/testthat/test-construction.R index 3651f71..50cf677 100644 --- a/tests/testthat/test-construction.R +++ b/tests/testthat/test-construction.R @@ -1,5 +1,3 @@ -context("construction") - test_that("input must be list of raw blobs", { # error from vctrs package expect_error(new_blob(1)) diff --git a/tests/testthat/test-format.R b/tests/testthat/test-format.R index 0f5391c..9f9149f 100644 --- a/tests/testthat/test-format.R +++ b/tests/testthat/test-format.R @@ -1,5 +1,3 @@ -context("format") - expect_format_equal <- function(formatted, result) { expect_equal( paste(formatted, collapse = "\n"), diff --git a/tests/testthat/test-missing.R b/tests/testthat/test-missing.R index 7753b4e..b692c46 100644 --- a/tests/testthat/test-missing.R +++ b/tests/testthat/test-missing.R @@ -1,5 +1,3 @@ -context("missing") - test_that("is.na detects nulls", { x <- blob(as.raw(1), NULL, as.raw(2), NULL) expect_equal(is.na(x), c(FALSE, TRUE, FALSE, TRUE)) From cd25a8f235b11d4b1c50d85ed98ddebea0996e7b Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:50:05 +0200 Subject: [PATCH 09/11] Do not show HTML preview --- README.Rmd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.Rmd b/README.Rmd index 55afcd3..b621d9d 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,5 +1,7 @@ --- -output: github_document +output: + github_document: + html_preview: false --- From 650ff787cd9351766120937903bebc69c5c43b09 Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:57:28 +0200 Subject: [PATCH 10/11] Create separate index.md for consumption by pkgdown --- README.Rmd | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.Rmd b/README.Rmd index b621d9d..8245159 100644 --- a/README.Rmd +++ b/README.Rmd @@ -21,6 +21,41 @@ knitr::opts_chunk$set( comment = "#>", fig.path = "README-" ) + +clean_output <- function(x, options) { + x <- gsub("0x[0-9a-f]+", "0xdeadbeef", x) + x <- gsub("dataframe_[0-9]*_[0-9]*", " dataframe_42_42 ", x) + x <- gsub("[0-9]*\\.___row_number ASC", "42.___row_number ASC", x) + + index <- x + index <- gsub("─", "-", index) + index <- strsplit(paste(index, collapse = "\n"), "\n---\n")[[1]][[2]] + writeLines(index, "index.md") + + x <- gsub( + '(`vignette[(]"([^"]+)"[)]`)', + "[\\1](https://blob.tidyverse.org/articles/\\2.html)", + x + ) + x <- fansi::strip_sgr(x) + x +} + +options( + cli.num_colors = 256, + cli.width = 71, + width = 71, + pillar.bold = TRUE, + pillar.max_title_chars = 5, + pillar.min_title_chars = 5, + pillar.max_footer_lines = 12, + conflicts.policy = list(warn = FALSE) +) + +local({ + hook_source <- knitr::knit_hooks$get("document") + knitr::knit_hooks$set(document = clean_output) +}) ``` # blob From fd305f74c8a2541c9d6ff4754e78e23a976d70bc Mon Sep 17 00:00:00 2001 From: MikeJohnPage <38110953+MikeJohnPage@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:57:47 +0200 Subject: [PATCH 11/11] Build README --- README.md | 2 +- index.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 index.md diff --git a/README.md b/README.md index 51a74e5..95cf37d 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ To create a blob, use `blob()`, `new_blob()` or `as_blob()`: library(blob) x1 <- charToRaw("Good morning") -x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f)) +x2 <- as.raw(c(0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef)) new_blob(list(x1, x2)) #> diff --git a/index.md b/index.md new file mode 100644 index 0000000..1af798f --- /dev/null +++ b/index.md @@ -0,0 +1,57 @@ + + +[![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) +[![rcc](https://github.com/tidyverse/blob/workflows/rcc/badge.svg)](https://github.com/tidyverse/blob/actions) +[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/blob)](https://cran.r-project.org/package=blob) +[![Coverage Status](https://codecov.io/gh/tidyverse/blob/branch/main/graph/badge.svg)](https://app.codecov.io/gh/tidyverse/blob) + + + + + + +# blob blob website + +## Overview + +The goal of blob is to provide a simple S3 class to represent a vector of binary objects, aka blobs. The `blob` class is a lightweight wrapper around a list of raw vectors, suitable for inclusion in a data frame. + +In most cases you will not need to use this package explicitly: it will be used transparently by packages that need to load BLOB columns from databases or binary file formats. + +## Installation + +```r +# The easiest way to get blob is to install the whole tidyverse: +install.packages("tidyverse") + +# Alternatively, install just blob: +install.packages("blob") + +# Or the the development version from GitHub: +# install.packages("pak") +pak::pak("tidyverse/blob") +``` + +## Example + +To create a blob, use `blob()`, `new_blob()` or `as_blob()`: + + +``` r +library(blob) + +x1 <- charToRaw("Good morning") +x2 <- as.raw(c(0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef)) + +new_blob(list(x1, x2)) +#> +#> [1] blob[12 B] blob[5 B] +blob(x1, x2) +#> +#> [1] blob[12 B] blob[5 B] + +as_blob(c("Good morning", "Good evening")) +#> +#> [1] blob[12 B] blob[12 B] +``` +