diff --git a/DESCRIPTION b/DESCRIPTION index 1286c36..8cc03ba 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,8 +26,6 @@ VignetteBuilder: quarto Config/testthat/edition: 3 URL: https://hugogruson.fr/grumpy/, https://github.com/Bisaloo/grumpy BugReports: https://github.com/Bisaloo/grumpy/issues -Imports: - jsonlite Config/Needs/website: Huber-group-EMBL/Rarr Config/roxygen2/version: 8.0.0 diff --git a/R/read_npy.R b/R/read_npy.R index 6ad9e3b..6a68643 100644 --- a/R/read_npy.R +++ b/R/read_npy.R @@ -88,8 +88,7 @@ parse_npy_descr <- function(bytes) { # We just ignore it, at least for now. header <- bytes |> rawToChar() |> - convert_py_dict_to_json() |> - jsonlite::fromJSON(simplifyMatrix = FALSE) + py_dict_to_r_list() parsed_descr <- parse_npy_datatype(header$descr) @@ -251,13 +250,30 @@ convert_bytes_to_array <- function(bytes, what, shape, size, endian) { return(res) } -convert_py_dict_to_json <- function(dict_str) { - dict_str |> - gsub("'", '"', x = _, fixed = TRUE) |> - gsub("None", "null", x = _, fixed = TRUE) |> - gsub("True", "true", x = _, fixed = TRUE) |> - gsub("False", "false", x = _, fixed = TRUE) |> - gsub("(", "[", x = _, fixed = TRUE) |> - gsub(")", "]", x = _, fixed = TRUE) |> - gsub(",\\s*(}|\\])", "\\1", x = _) # trailing commas +py_dict_to_r_list <- function(x) { + x |> + # Logicals + gsub("\\bNone\\b", "NA", x = _) |> + gsub("\\bTrue\\b", "TRUE", x = _) |> + gsub("\\bFalse\\b", "FALSE", x = _) |> + # Trailing commas (before closing brackets/braces) + gsub(",\\s*([]})])", "\\1", x = _) |> + # Dict (single-quoted) keys to list names. + # Keys are composed of: + # - anything that is not the quote itself or a backslash, + # - a backslash followed by any character (to allow for escaped quotes). + gsub("'(([^'\\\\]|\\\\.)*)'\\s*:", "'\\1' =", x = _) |> + # Dict (double-quoted) keys to list names. + gsub('"(([^"\\\\]|\\\\.)*)"\\s*:', '"\\1" =', x = _) |> + # Tuples to c(...) + gsub("(", "c(", x = _, fixed = TRUE) |> + # Lists to list(...) + gsub("[", "list(", x = _, fixed = TRUE) |> + gsub("{", "list(", x = _, fixed = TRUE) |> + # Closing brackets/braces + gsub("]", ")", x = _, fixed = TRUE) |> + gsub("}", ")", x = _, fixed = TRUE) |> + # Evaluate the resulting R expression + parse(text = _) |> + eval() } diff --git a/README.md b/README.md index c9cae22..d71740a 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ As a file format generated by a Python package, `.npy` files are prime candidates for using the `{reticulate}` package to read them into R. However, this comes with downsides in terms of performance, flexibility, and robustness of the R package infrastructure. `{grumpy}`, on the other -hand, is a pure R package with a single dependency (`{jsonlite}`), and -is performant, flexible. Overall, it is designed to be used deep in the -dependency graph of other packages. +hand, is a pure R package with no dependency and is performant, +flexible. Overall, it is designed to be used deep in the dependency +graph of other packages. For more details on the motivation and design principles underpinning `{grumpy}`, see the dedicated vignette: diff --git a/README.qmd b/README.qmd index 7d85868..a2292cf 100644 --- a/README.qmd +++ b/README.qmd @@ -27,7 +27,7 @@ The `{grumpy}` R package provides a way to read NumPy's `.npy` files into R. It As a file format generated by a Python package, `.npy` files are prime candidates for using the `{reticulate}` package to read them into R. However, this comes with downsides in terms of performance, flexibility, and robustness of the R package infrastructure. -`{grumpy}`, on the other hand, is a pure R package with a single dependency (`{jsonlite}`), and is performant, flexible. Overall, it is designed to be used deep in the dependency graph of other packages. +`{grumpy}`, on the other hand, is a pure R package with no dependency and is performant, flexible. Overall, it is designed to be used deep in the dependency graph of other packages. For more details on the motivation and design principles underpinning `{grumpy}`, see the dedicated vignette: `vignette("design", package = "grumpy")`.