Skip to content
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: 0 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 27 additions & 11 deletions R/read_npy.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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()
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion README.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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")`.

Expand Down
Loading