wahani / modules

Modules in R
https://cran.r-project.org/package=modules
Other
81 stars 3 forks source link

document package with Roxygen clash by using functions import and export #27

Closed Mandano89 closed 3 years ago

Mandano89 commented 4 years ago

I am trying to create the package documentation for my project with Roxygen by using devtools:document(my_package). I am using the import and export functions of the Modules package to import other packages like shiny, R6 etc.

The problem is when I try do create the documentation and use the import function in one of my scripts I get the error "no item called \"imports_env(package)\" on the search list" and by using the export function I get "object '.exports' not found". Is there a solution for that or maybe a way to exclude some code lines like the imports and exports in my other scripts?

wahani commented 4 years ago

Thanks for taking the time to report this issue. You can find some references on how to use modules inside of packages in https://cran.r-project.org/web/packages/modules/vignettes/modulesAsObjects.html From there:

As you would avoid using library inside of packages, you should also avoid using modules::import. The R package namespace mechanism is more than capable of handling all dependencies.

Inside of packages a module has access to the package namespace; it is not just referencing the base environment. So my recommendation would be to use rxygen2 (imports/exports) to manage your namespace. In a module you may reference shiny/R6 objects using pkg::fun notation, or relying on lexical scoping.

The problem is when I try do create the documentation and use the import function in one of my scripts I get the error "no item called "imports_env(package)" on the search list" and by using the export function I get "object '.exports' not found". Is there a solution for that or maybe a way to exclude some code lines like the imports and exports in my other scripts?

Not sure I can diagnose this without an example. In any case: modules::import and modules::export will only work inside of a module. Can it be, that you are calling them in a package directly? You may want to wrap you code in a pattern like:

mymodule <- modules::module({
    export(myexport)
    myexport <- function(x) x
})

inside your package. You can then Export the module from you package or even better, wrap them in function calls and use roxygen2 for documentation. You can see an example here: https://github.com/wahani/REPLesentR/blob/master/R/SlideDeck.R

Not sure if this helps. If not, I would need an example to give more feedback.

Mandano89 commented 4 years ago

Thank you very much for your quick response! The problem is I don't want to create a package. Roxygen is only working with packages so I am creating a dummy package where all the module files get automatically copied from the original project. After this I create the Rd files with devtools::document and then copy them back again in the original project directory. I wrapped it all up in one function. So my main goal is to create the documentation for my project without creating a real package for the project.

An example module for it is this:

import("R6")

#' R6 Class representing a person
#'
#' A person has a name and a hair color.

Person <- R6Class("Person",
                      public = list(
                        #' @field name First or full name of the person.
                        name = NULL,

                        #' @field hair Hair color of the person.
                        hair = NULL,

                        #' @description
                        #' Create a new person object.
                        #' @param name Name.
                        #' @param hair Hair color.
                        #' @return A new `Person` object.
                        initialize = function(name = NA, hair = NA) {
                          self$name <- name
                          self$hair <- hair
                          self$greet()
                        },

                        #' @description
                        #' Change hair color.
                        #' @param val New hair color.
                        #' @examples
                        #' P <- Person("Ann", "black")
                        #' P$hair
                        #' P$set_hair("red")
                        #' P$hair
                        set_hair = function(val) {
                          self$hair <- val
                        },

                        #' @description
                        #' Say hi.
                        greet = function() {
                          cat(paste0("Hello, my name is ", self$name, ".\n"))
                        }
                      )
)

When I use the devtools:document function with the path to the dummy package it is unable to create the documentation and there comes up the already mentioned errors.

wahani commented 4 years ago

I have had my share of fighting tooling around R, and have to say, it is rarely worth the effort. There is no better way to transport documentation of source code than Rs package system. It is one of the selling points of the language. If there is something holding you back from using a R package I'd rather help you with that.

Anyway, to make some progress in your current setup: The problem is, that import and export expect to be called inside of a module. A module has certain properties, like a hidden .exports object, used by the export mechanism. There is really not much you can do about it, except getting rid of modules, or wrap up you code above in a modules::module block. In the latter approach I am unsure how devtools::document deals with that. Another option may be to parse the file and delete the imports and exports, then apply devtools::document.

wahani commented 4 years ago

Just as a side note. There are other documentation frameworks that you can use aside from roxygen2. They may be more fitting to your use-case. If you search through the packages on CRAN you find several of them. I have no experience with any of them, but it may be worth checking out. I doubt that any of them provides as many features as roxygen2.

Mandano89 commented 4 years ago

Thanks for the help! FYI, I tried your solutions and wrapped up the code in a modules::module block. Now I am able to create an Rd file with roxygen::document but all the methods are missing.

wahani commented 4 years ago

If you are really into it, than you may have to:

Another option may be to parse the file and delete the imports and exports, then apply devtools::document.

You read (readLines) in the file you want to document. Remove lines with import/export and write it back into a temporary file. Then apply roxygen document. Then clean up. Aside from the recommendation I gave above, I am not sure what else you can do.

Mandano89 commented 4 years ago

Thank you very much for your help. Your approach works. I also want to use module::use. Do you have any idea how to make this work with roxygen2? Because if I want to use a function from another file Roxygen isn't able to find the function from the given script in module::use

wahani commented 4 years ago

I also want to use module::use. Do you have any idea how to make this work with roxygen2?

Can you prepare an example of the setting?

Mandano89 commented 4 years ago

Here is an example:

haha <- use("ui/hausManager.R")$hausManager

#' R6 Klasse repräsentiert blabla
#'
#' @description
#' Die Applikation dient blabla

App = R6Class(
  "App",

  private = list(
    hausManager = NULL
  ),

  public = list(
    initialize = function() {
      private$hausManager <- haha$new("hausManager")
    }
  )
)

I don't know if this helps but the problem is roxygen is not able to load the hausManager because roxygen goes just through the script so it can't find some functions that are in hausManager

wahani commented 4 years ago

@Mandano89 it would be helpful to get more details, this is not reproducible for me. How exactly does the environment of this file looks like? devtools expects a package, so we also need to see the complete folder structure. I am assuming, you are not really in a package, so I would need to see the exact steps until we get the error. Maybe this would be easier with a github repository.

When R compiles a package, then the only available files are in ./R. From there you are trying to read in the ui/hausManager.R file. Is that folder and file really available? Subfolders are typically not part of the .R folder. Usually they are simply ignored.

wahani commented 3 years ago

Seems to be inactive or resolved. Please feel free to reopen.