# filter out function handles that also have class handles
endpoints <- endpoints %>%
lapply(\(endpoint) {
if(!any(startsWith(endpoint, c("keras.losses.", "keras.metrics."))))
return(endpoint)
py_obj <- py_eval(endpoint)
if (!inherits(py_obj, "python.builtin.function"))
return(endpoint)
class_endpoint <- switch(endpoint,
"keras.losses.kl_divergence" = "keras.losses.KLDivergence",
str_replace(endpoint, py_obj$`__name__`,
snakecase::to_upper_camel_case(py_obj$`__name__`)))
tryCatch({
py_eval(class_endpoint)
return(NULL)
},
python.builtin.AttributeError = function(e) {
# don't emit warning about known function handles without class handle
# counterparts
if (!endpoint %in% sprintf(
"keras.metrics.%s", c(
"binary_focal_crossentropy",
'categorical_focal_crossentropy',
'huber',
'kl_divergence',
'log_cosh')))
# browser()
print(e)
endpoint
})
}) %>%
unlist() %>%
invisible()
get_metric_counterpart_endpoint <- function(..., fn, type) {
if(missing(fn)) {
endpoint <- type
py_obj <- py_eval(endpoint)
name <- py_obj$`__name__`
endpoint_fn <- str_replace(endpoint, name, snakecase::to_snake_case(name))
py_obj_fn <- py_eval(endpoint_fn) %error% browser()
}
}
list.files("man-src", pattern = "\\.Rmd$", full.names = TRUE) %>%
map(\(f) {
f |>
read_lines() |>
str_replace_all("([^ ])=([^ ])", "\\1 = \\2") |>
# TODO `True`, None
str_trim("right") %>%
write_lines(f)
})
# {
#
# render_roxygen_rmds <- function(filepath = fs::dir_ls("man-src/", type = "directory")) {
# # this should probably happen in a separate R session...
# filepath |>
# fs::as_fs_path() |>
# # head(3) |>
# set_names(basename) %>%
# purrr::walk(\(dir) {
# withr::local_dir(dir)
# message("rendering: ", dir)
# keras$utils$clear_session()
# # Set knitr options to halt on errors
# knitr::opts_chunk$set(error = FALSE)
# knitr::knit("2-translated.Rmd", "3-rendered.md",
# quiet = TRUE, envir = new.env())
# x <- readLines("3-rendered.md")
# # TODO: these filters should be confined to chunk outputs only,
# # probably as a knitr hook
# x <- x |> str_replace_all(" at 0x[0-9A-F]{9}>$", ">")
# x <- x[!str_detect(x, r"{## .*rstudio:run:reticulate::py_last_error\(\).*}")]
# x |> writeLines("3-rendered.md")
# })
# # discard(\(x) is.null(x) || x == 0) |>
# # invisible()
# }
# }
#
# man_src_pull_upstream_updates2 <- function() {
#
# vscode_settings <- og_vscode_settings <-
# jsonlite::read_json(".vscode/settings.json")
# vscode_settings %<>% modifyList(list("git.autorefresh" = FALSE,
# "git.autofetch" = FALSE))
# jsonlite::write_json(vscode_settings, ".vscode/settings.json")
# withr::defer(jsonlite::write_json(og_vscode_settings, ".vscode/settings.json",
# pretty = TRUE))
#
# fs::dir_ls("man-src/", type = "directory") |>
# # head(3) |>
# # keep(~str_detect(.x, "backup|_elu|_relu")) %>%
# set_names(dirname) |>
# walk(\(dir) {
# # withr::local_dir(dir)
# old_upstream <- read_lines(path(dir, "0-upstream.md"))
# endpoint <- old_upstream[1]
# old_upstream <- str_flatten_lines(old_upstream)
# new_upstream <- format_man_src_0(endpoint)
# # if(new_upstream == old_upstream) return() # nothing to update
#
#
# export <- mk_export(endpoint)
#
# if (!file.exists(dir / "2-translated.Rmd")) {
# write_lines(export$roxygen, dir/"1-formatted.md")
# write_lines(export$roxygen, dir/"2-translated.Rmd")
# return()
# }
# write_lines(export$roxygen, dir/"1-formatted-new.md")
# write_lines(export$roxygen, dir/"2-translated-new.Rmd")
#
# # -m --merge <path1> <path2> <base> <result>
# # Perform a three-way merge by providing paths for two modified versions of
# # a file, the common origin of both modified versions and the output file
# # to save merge results.
#
# system2("code", c("--merge",
# dir / "2-translated.Rmd",
# dir / "1-formatted-new.md",
# dir / "1-formatted.md",
# dir/ "2-translated.Rmd"))
# # stop()
# # if(!identical(res, 0L)) {
# # cat("res <- "); dput(res)
# # stop("non-0 exit from git apply")
# # }
# # stop()
# })
# }; man_src_pull_upstream_updates2()
# man_src_reformat_0 <- function() {}
# man_src_pull_upstream_updates()
#
#
# man_src_render
#
# vignettes_src_pull_upstream_updates
# vignettes_src_render
make_translation_patchfiles <- function() {
fs::dir_ls("man-src/", type = "directory") |>
# head(3) |>
# keep(~str_detect(.x, "backup|_elu|_relu")) %>%
set_names(dirname) |>
walk(\(dir) {
# withr::with_dir(dir, {
# # timestamps don't work because the translation file gets rewritten.
# doesnt_need_update <- file_exists("translate.patch") &&
# file_info("2-translated.Rmd")$change_time < file_info("translate.patch")$birth_time
# }
# )
# if(doesnt_need_update) return()
# message("updating patchfile: ", dir)
diff <- suppressWarnings( # returns 1 on diff
system2t("git", c("diff -U1 --no-index",
# "--diff-algorithm=minimal",
glue("--output={dir}/translate.patch"),
dir / "1-formatted.md", dir / "2-translated.Rmd")))
patch_filepath <- dir/"translate.patch"
patch <- read_lines(patch_filepath)
if(!length(patch)) return()
# if(grepl("hard_sigmoi", dir)) browser()
patch <- patch[-2] # drop index <hash>..<hash> line
patch[1:3] <- str_replace(patch[1:3], fixed("/1-formatted.md"), "/2-translated.Rmd")
write_lines(patch, patch_filepath)
# str_replace(fixed("/1-formatted.md"), "/2-translated.Rmd") |>
# | sed 's|1-formatted.md|2-translated.Rmd|' > translate.patch")
# system2("git", c("diff --output=translate.patch --diff-algorithm=minimal -U1 --no-index",
# "1-formatted.md 2-translated.Rmd "))
})
}
apply_translation_patchfiles <- function(filepath = fs::dir_ls("man-src/", type = "directory") ) {
filepath |>
fs::as_fs_path() |>
# head(3) |>
set_names(basename) %>%
purrr::walk(\(dir) {
# withr::local_dir(dir)
system2t("git", c("apply --no-index --recount --allow-empty", # --3way
dir/"translate.patch"))
# system(glue("patch -p2 < {dir}/translate.patch"))
# TODO: this needs to propogate errors up from applying the patchfile
}) |>
discard(\(x) is.null(x) || x == 0) |>
invisible()
}
# "git apply --3way --allow-empty translate.patch"
make_translation_patchfiles()
# z <- "man-src/activation_elu/2-translated.Rmd" |> read_file() |>
# get_translated_roxygen()
#
# apply_translation_patchfiles()
# write_lines(z, "man-src/activation_elu/2-translated.Rmd") -> z2
# source("tools/utils.R")
if(FALSE)
local({
x <- keras$callbacks$BackupAndRestore
x$`__doc__` <- str_replace(keras$callbacks$BackupAndRestore$`__doc__`, "Note that the user", "Note that the user asdfa asdfdsaf asdfasdf ")
})
# fs::path("tools/raw", gsub(".", "-", endpoint, fixed = TRUE), ext = "R")
#
# make_patch_files <- function() {
# fs::dir_ls("man-src/", type = "directory") |>
# # head(3) |>
# purrr::walk(\(dir) {
# # fs::dir_map("man-src/", type = "directory", \(dir) {
# withr::local_dir(dir)
# # print(dir)
# # https://git-scm.com/docs/git-diff
# system2("git", c("diff --output=translate.patch --diff-algorithm=minimal -U1",
# "1-formatted.md 2-translated.Rmd"))
# }) #|> invisible()
# }
# make_patch_files()
#
# apply_patch_files <- function() {
# fs::dir_map("man-src/", \(dir) {
# withr::local_dir(dir)
#
# })
# }
update_man_src_dir <- function(ex) {
message("updating ", ex$r_name)
withr::local_dir(ex$man_src_dir)
# old_docstring <- "0-docstring.md" |> readLines() |> str_flatten_lines()
# is_changed <- ex$docstring != old_docstring
# if(!is_changed) {
# message("returning early")
# return(ex)
# }
import_from({ex}, docstring, roxygen)
# old_docstring_as_roxygen <- read_file("1-formatted.md")
# old_roxygen_rmd <- read_file("2-translated.Rmd")
# system("git diff -u1 1-formatted.md 2-translated.Rmd > fixup.patch")
writeLines(docstring, "0-docstring.md") # 0-original.md
writeLines(roxygen, "1-formatted.md") # 1-formatted.md
writeLines(roxygen, "2-translated.Rmd") # 2-translated.md
writeLines(str_flatten_lines( # 3-rendered.md
str_c(ex$r_name, " <-"),
deparse(ex$r_fn)
), "function.R")
# res <- system("git apply --3way translate.patch") # --unidiff-zero --verbose
ex
# if res == error: nothing else: knitr::knit() ?
# knitting should really be a separate step...
}
augment_export <- function(ex) {
ex$man_src_dir <- glue("man-src/{ex$r_name}/")
if (fs::dir_exists(ex$man_src_dir))
update_man_src_dir(ex)
else
make_new_man_src_dir(ex)
ex
}
exports <- exports |>
map(augment_export)
# apply_translation_patchfiles("man-src/callback_backup_and_restore")
apply_translation_patchfiles()
# stop("here")
render_roxygen_rmds <- function(filepath = fs::dir_ls("man-src/", type = "directory")) {
# this should probably happen in a separate R session...
filepath |>
fs::as_fs_path() |>
# head(3) |>
set_names(basename) %>%
purrr::walk(\(dir) {
withr::local_dir(dir)
message("rendering: ", dir)
keras$utils$clear_session()
# Set knitr options to halt on errors
knitr::opts_chunk$set(error = FALSE)
knitr::knit("2-translated.Rmd", "3-rendered.md",
quiet = TRUE, envir = new.env())
x <- readLines("3-rendered.md")
# TODO: these filters should be confined to chunk outputs only,
# probably as a knitr hook
x <- x |> str_replace_all(" at 0x[0-9A-F]{9}>$", ">")
x <- x[!str_detect(x, r"{## .*rstudio:run:reticulate::py_last_error\(\).*}")]
x |> writeLines("3-rendered.md")
})
# discard(\(x) is.null(x) || x == 0) |>
# invisible()
}
render_roxygen_rmds()
devtools::document(roclets = c('rd', 'namespace'))
stop("DONE", call. = FALSE)
# git add man-src/*/2-*
"file.edit('man-src/callback_progbar_logger/2-translated.Rmd')" %>%
cli::style_hyperlink(., paste0("ide:run:", .)) %>%
dput()
# file.edit('man-src/callback_progbar_logger/2-translated.Rmd')
# df <- df %>%
# mutate(man_src_dir = fs::dir_create(glue("man-src2/{r_name}/")))
ex <- exports$keras.layers.Hashing
ex2 <- augment_export(exports$keras.activations.elu)
setwd(ex2$man_src_dir)
rmarkdown::render("2-translated.Rmd", #run_pandoc =
# output_format = "github_document",
output_format = rmarkdown::github_document(
hard_line_breaks = TRUE,
html_preview = FALSE
# pandoc_args = c()
),
# quiet = TRUE,
output_file = "roxygen.md", envir = new.env())
knitr::knit("2-translated.Rmd", "roxygen.md")
setwd(here::here())
ex2 <- augment_export(export)
df %>%
split_by
if(FALSE) {
df %>%
rowwise() %>%
mutate(write_out = withr::with_dir(man_src_dir, {
writeLines(docstring, "0-docstring.md")
writeLines(roxygen, "roxygen_intermediate.md")
writeLines(roxygen, "2-translated.Rmd")
writeLines(roxygen, "roxygen.md")
}))
# dump_file = glue("src/wrappers/{r_name}/r_wrapper_raw.R")) %>%
df <- dfo %>%
mutate(dump_file = glue("src/wrappers/{r_name}/r_wrapper_raw.R")) %>%
rowwise() %>%
mutate(
raw_dumpfile = str_flatten_lines(
str_glue("# {endpoint}"),
str_glue("# {module}.{name}"),
str_c('r"-{', trim(docstring), '}-"'),
"",
dump
),
old_dumpfile = dumpfile_path %>% {if(file.exists(.)) {message("exists: ", .); str_flatten_lines(readLines(.))} else "''"},
old_docstring = str2expression(old_dumpfile)[[1]]) %>%
ungroup() %>%
mutate(is_new = !file.exists(dumpfile_path),
is_changed = (!is_new) & docstring != old_docstring)
df_new <- df %>% filter(is_new)
df_new %>%
rowwise() %>%
mutate(writeout = {
writeLines(dumpfile, dumpfile_path)
})
df_changed <- df %>% filter(is_changed)
stop("!!!")
df <- df %>%
rowwise() %>%
mutate(
) %>%
# writeLines(txt, dump_filepath)
# dump_filepath
# ) %>%
ungroup()
df$dumpfile
}
# filter(endpoint_sans_name %in% c("layers", "ops", "constraints", "initializers",
# "callbacks", "optimizers",
# "preprocessing",
# "preprocessing.image",
# "preprocessing.sequence",
# "losses", "metrics",
# "optimizers.schedules",
# # "utils",
# "applications",
# "activations", "regularizers")) |> #
# select(endpoint, r_name, module, type) |>
# |>
dplyr::bind_rows()
map(xx, format)
# tibble(endpoint = _) |>
mutate(name = endpoint |>
str_replace_all(fixed("."), "$") |>
map(\(s) names(eval(str2lang(s))))) |>
tidyr::unchop(name) |>
filter(!name %in% c("experimental", "deserialize", "serialize")) |>
mutate(endpoint = str_c(endpoint, name, sep = ".")) |>
filter(!endpoint %in% "keras.Sequential.build") #|>
# start w/ the export endpoint, and augment it.
x <- mk_export("keras.layers.PReLU")
x
# TODO:
#
# Parsing of params for keras$ops$tensordot isn't right
#
# TODO: @returns required for every obj
#
#
# TODO:
# layer_wrapper?
# layer_torch_module_wrapper?
# layer_time_distributed?
# layer_tfsm_layer?
# layer_bidirectional
# Seemingly removed:
# layer_random_height
# layer_random_width
# layer_locally_connected_{12}d
# layer_cudnn_*
# layer_dense_features
# layer_alpha_dropout
# layer_activation_thresholded_relu
# TODO: "activation layers" not "activations layers" as a family tag
# map_chr(df$tags, ~.x$"family" %||% '') %>% unique() %>% writeLines()
# activation functions
# callback
# core layers
# convolutional layers
# pooling layers
# activations layers
# merging layers
# normalization layers
# reshaping layers
# attention layers
# preprocessing layers
# regularization layers
# recurrent layers
# constraint
# initializer
# loss
# metric
# ops
# optimizer
# learning_rate_schedule
make_r_fn("keras.layers.PReLU")
mk_export("keras.layers.PReLU")
mk_export("keras.applications.VGG16")
mk_export("keras.ops.conv_transpose")$dump |> cat()
roxygen2::parse_file("/Users/tomasz/github/rstudio/keras/R/autogen-layers-core.R") -> r
# TODO: UpSampling1D needs fixup
r[[3]] -> r
r
r$tags[[2]]
trace(system2, quote(message(paste("+", paste0(env, collapse = " "),
shQuote(command), paste0(shQuote(args), collapse = " "))))); tools:::..Rd2pdf(".")
mk_export("keras.layers.LayerNormalization")$doc$description -> d
str()
str_sppulit_1(fixed("\n```")) %>%
{
length(.) <- ceiling(length(.)/2)*2 # maybe resize to multiple of 2
dim(.) <- c(2, length(.) / 2)
rownames(.) <- c("prose", "code")
.
} %>% {
p <- .["prose",]
}
print()
str()
# TODO: callback_progbar logger ... the documented arg doesn't seem to actually be accepted,
# also, does it make sense to export it?
#
"keras.constraints.to_snake_case" # ??
# if (any(str_detect(df$endpoint, "metrics|losses"))) {
#
# nms_in <- names(df)
# df <- df |>
# mutate(
# name = map_chr(py_obj, \(o) o$`__name__`),
# module = map_chr(py_obj, \(o) o$`__module__`)) |>
# rowwise() %>%
# mutate(
# dist_from_true_home = adist(str_replace(endpoint, name, ""),
# module)
# ) |>
# ungroup() |>
# arrange(dist_from_true_home, desc(nchar(name)))
# # message(str_flatten_comma(df$endpoint, ", "))
# df %>%
# # slice(1) %>%
# select(!!nms_in)
# } else {
#
#
# l <- keras$layers$PReLU
#
#
# l$`__doc__` |> trim() |> split_docstring_into_sections()
#
# cat()
n_openai_calls_made <- 0L
max_openai_calls <- 1L
make_new_man_src_dir <- function(ex) {
ex$man_src_dir |>
fs::dir_create() |>
withr::local_dir()
ex$is_new <- TRUE
ex$is_changed <- FALSE
ex$old_docstring <- ""
ex$old_roxygen_intermediate <- ""
import_from({ex}, docstring, roxygen)
writeLines(docstring, "0-docstring.md")
writeLines(roxygen, "1-formatted.md")
do_call_openai <-
(n_openai_calls_made < max_openai_calls) &&
str_detect(roxygen, "```python")
if (do_call_openai) {
ex$completion <- completion <- get_translated_roxygen(roxygen)
n_openai_calls_made <<- n_openai_calls_made + 1L
write_rds(completion, "completion.rds")
writeLines(completion, "2-translated.Rmd")
tryCatch({
library(keras3)
keras$utils$clear_session()
knitr::knit("2-translated.Rmd", "roxygen.md",
quiet = TRUE, envir = new.env())
}, error = function(e) {
warning("Failed to render docs for", ex$r_name)
})
} else {
writeLines(roxygen, "2-translated.Rmd")
file.copy("2-translated.Rmd", "roxygen.md")
}
ex
}
if(FALSE) {
exports$keras.activations.relu$docstring <-
read_file(fs::path("man-src",
exports$keras.activations.relu$r_name,
"0-docstring.md"))
augment_export(exports$keras.activations.relu)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.