Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automate R docs build from roxygen comments #205

Merged
merged 2 commits into from
Jan 29, 2024
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
15 changes: 14 additions & 1 deletion .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,25 @@ jobs:
- name: Set up Julia
uses: julia-actions/setup-julia@v1

- name: Install package

- name: Install R
uses: r-lib/actions/setup-r@v2.6.5

- name: Install R dependencies
uses: r-lib/actions/setup-r-dependencies@v2.6.5
with:
packages: |
any::roxygen2
github::Genentech/rd2markdown

- name: Install packages
run: |
cd python/
pip install .
cd ../julia
julia --project=./docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
cd ../R/
Rscript -e "install.packages(getwd(), repos=NULL, type=\"source\")"

- name: Calculate version
if:
Expand Down
2 changes: 1 addition & 1 deletion R/R/bridgestan.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' StanModel
#'
#' R6 Class representing a compiled BridgeStan model.
#' @description R6 Class representing a compiled BridgeStan model.
#'
#' This model exposes log density, gradient, and Hessian information
#' as well as constraining and unconstraining transforms.
Expand Down
34 changes: 19 additions & 15 deletions R/R/compile.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@ IS_WINDOWS <- isTRUE(.Platform$OS.type == "windows")
MAKE <- Sys.getenv("MAKE", ifelse(IS_WINDOWS, "mingw32-make", "make"))


#' Get the path to BridgeStan.
#'
#' By default this is set to the value of the environment
#' variable `BRIDGESTAN`.
#'
#' If there is no path set, this function will download
#' a matching version of BridgeStan to a folder called
#' `.bridgestan` in the user's home directory.
#'
#' See also `set_bridgestan_path`
verify_bridgestan_path <- function(path) {
suppressWarnings({
folder <- normalizePath(path)
Expand All @@ -26,15 +16,25 @@ verify_bridgestan_path <- function(path) {
}
}

#' Set the path to BridgeStan.
#'
#' This should point to the top-level folder of the repository.
#' @title Function `set_bridgestan_path()`
#' @description Set the path to BridgeStan.
#' @details This should point to the top-level folder of the repository.
#' @export
set_bridgestan_path <- function(path) {
verify_bridgestan_path(path)
Sys.setenv(BRIDGESTAN = normalizePath(path))
}

#' Get the path to BridgeStan.
#'
#' By default this is set to the value of the environment
#' variable `BRIDGESTAN`.
#'
#' If there is no path set, this function will download
#' a matching version of BridgeStan to a folder called
#' `.bridgestan` in the user's home directory.
#'
#' @seealso [set_bridgestan_path]
get_bridgestan_path <- function() {
# try to get from environment
path <- Sys.getenv("BRIDGESTAN", unset = "")
Expand All @@ -54,8 +54,10 @@ get_bridgestan_path <- function() {
}


#' Run BridgeStan's Makefile on a `.stan` file, creating the `.so`
#' used by the StanModel class.
#' @title Function `compile_model()`
#' @description Compiles a Stan model.
#' @details Run BridgeStan's Makefile on a `.stan` file, creating
#' the `.so` used by the StanModel class.
#' This function checks that the path to BridgeStan is valid
#' and will error if not. This can be set with `set_bridgestan_path`.
#'
Expand All @@ -67,6 +69,8 @@ get_bridgestan_path <- function() {
#' threading for the compiled model. If the same flags are defined
#' in `make/local`, the versions passed here will take precedent.
#' @return Path to the compiled model.
#'
#' @seealso [bridgestan::set_bridgestan_path()]
#' @export
compile_model <- function(stan_file, stanc_args = NULL, make_args = NULL) {
verify_bridgestan_path(get_bridgestan_path())
Expand Down
30 changes: 30 additions & 0 deletions R/convert_docs.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Converts R documentation (.Rd) files to markdown (.md) files
# for use in Sphinx.

library(rd2markdown)
library(roxygen2)

roxygen2::roxygenize()

files <- list.files("man", pattern="*.Rd")

# we only want to doc exported functions, so we need
# to read the NAMESPACE file
namespace <- paste0(readLines("NAMESPACE"), collapse="\n")

for (f in files){
name <- substr(f, 1, nchar(f)-3)

if (!grepl(name, namespace, fixed=TRUE)){
print(paste0("Skipping unexported ", name))
next
}

# read .Rd file and convert to markdown
rd <- rd2markdown::get_rd(file=file.path(".", "man", f))
md <- rd2markdown::rd2markdown(rd, fragments=c())

# write it to the docs folder
writeLines(md, file.path("..", "docs", "languages", "_r", paste0(name, ".md")))

}
5 changes: 0 additions & 5 deletions R/man/StanModel.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions R/man/compile_model.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions R/man/verify_bridgestan_path.Rd → R/man/get_bridgestan_path.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion R/man/set_bridgestan_path.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,30 @@
else:
print("Failed to build julia docs!\n", e)

try:
print("Building R doc")
subprocess.run(
["Rscript", "convert_docs.R"],
cwd=pathlib.Path(__file__).parent.parent / "R",
check=True,
)

# delete some broken links in the generated R docs
StanModel = (pathlib.Path(__file__).parent / "languages" / "_r" / "StanModel.md")
text = StanModel.read_text()
start = text.find("### Public methods")
end = text.find("### Method `")
text = text[:start] + text[end:]
StanModel.write_text(text)

except Exception as e:
# fail loudly in Github Actions
if RUNNING_IN_CI:
raise e
else:
print("Failed to build R docs!\n", e)


try:
print("Checking C++ doc availability")
import breathe
Expand Down
9 changes: 7 additions & 2 deletions docs/internals/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Documenting a mixed-language project such as BridgeStan can be tricky.

We attempt to keep documentation in the natural place for each language: C/C++
code is documented with doxygen-style comments in the source, Python documentation
appears in docstrings, etc. With the exception of the R interface, our documentation
generation (powered by `Sphinx <https://www.sphinx-doc.org/en/master/>`__) automatically
appears in docstrings, etc. Our documentation generation
(powered by `Sphinx <https://www.sphinx-doc.org/en/master/>`__) automatically
combines these together into the documentation you are reading now.

To build the documentation, you can run ``make docs`` in the top-level directory.
Expand All @@ -31,3 +31,8 @@ Similarly, the Julia documentation will only update if Julia is installed. Julia
documentation is written in :file:`julia/docs/src/julia.md`. We then build
this with `DocumenterMarkdown.jl <https://github.com/JuliaDocs/DocumenterMarkdown.jl>`__,
and the output is placed in :file:`docs/languages/julia.md`.

Finally, the R documentation is primarily written in :file:`/docs/languages/r.md`.
The API documentation for R is done by including files generated by
`rd2markdown <https://github.com/Genentech/rd2markdown>`__, which runs
on the results of the `roxygen2 package <https://roxygen2.r-lib.org/>`__.
3 changes: 3 additions & 0 deletions docs/languages/_r/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
These files are automatically generated in `conf.py` and should
not be manually edited. They are built from the documentation
comments in the R source code.
Loading
Loading