How to add class-specific alias without generic alias using Roxygen2? - r

A simple example is that I have created an extension to show, which is a S4 base method. I don't want to cause a disambiguation fork by re-documenting show in my package, and I also want to consolidate the documentation of my extension to show in the documentation for the new class, myPkgSpClass, by adding an alias for show,myPkgSpClass-method.
#' #export
#' #aliases show,myPkgSpClass-method
#' #rdname myPkgSpClass-class
setMethod("show", "myPkgSpClass", function(object){ show(NA) })
The problem I'm having, is that this results in an serious warning during documentation-build by roxygen2, Rd files with duplicated alias 'show': because there is more than one class extension to show in this package, and roxygen2 has automatically added the generic term in the list of aliases to all the relevant *-class.Rd files:
\alias{show}
\alias{show,myPkgSpClass-method}
But I think I don't want the generic alias in any of the instances, because it will force the need for disambiguation between show in my package, and the base show. This issue also applies to other S4 methods extended from other packages besides show.
If I tag all class-specific methods to the same .Rd file, then the warning goes away, but the ambiguity remains, because the show alias still gets added automatically for that doc entry. If I manually remove \alias{show} from the .Rd file, then the problem seems solved, no warnings during roxygen or R CMD check pkgname. So how do I get Roxygen2 to not-add the generic alias?
Other background:
This is a specific question building from a previous issue for exporting/documenting S4 extensions to base methods:
Is it necessary to export base method extensions in an R package? Documentation implications?
It is more specific than, and not covered by, the following questions regarding documenting S4 methods / classes using Roxygen2:
How to properly document S4 methods using roxygen2
How to properly document S4 class slots using Roxygen2?

Seems to be fixed in roxygen2_3.1.0:
#' #export
#' #aliases show,myPkgSpClass-method
#' #rdname myPkgSpClass-class
setMethod("show", "myPkgSpClass", function(object){ show(NA) })
produces the myPkgSpClass-class.Rd:
\docType{methods}
\name{show,myPkgSpClass-method}
\alias{show,myPkgSpClass-method}
\usage{
\S4method{show}{myPkgSpClass}(object)
}
\arguments{
\item{object}{Any R object}
}
As Hadley stated, you do not need anymore to explicitly set the alias or the rd name, e.g.:
#' my title
#' #export
setMethod("show", "myPkgSpClass", function(object){ show(NA) })
will generate show-myPkgSpClass-method.Rd:
\docType{methods}
\name{show,myPkgSpClass-method}
\alias{show,myPkgSpClass-method}
\title{my title}
\usage{
\S4method{show}{myPkgSpClass}(object)
}
\arguments{
\item{object}{Any R object}
}
\description{
my title
}
Note that in that case you have to set the description. It will not generate a doc page if the documentation entry is empty.

Related

Using R, how to specify that a function will NOT use default namespace (S3)? roxygen2? [duplicate]

Since roxygen2 version 4.0.0, the #S3method tag has been deprecated in favour of using #export.
The package now tries to detect if a function is an S3 method, and automatically adds the line S3method(function,class) to the NAMESPACE file if it think it is one.
The problem is that if a function is not an S3 method but its name contains a . then roxygen sometimes makes a mistake and adds the line when it shouldn't.
Is there a way to tell roxygen that a function is not an S3 method?
As requested, here's a reproducible example.
I have a package that imports R.oo, with a function named check.arg.
library(roxygen2)
package.skeleton("test")
cat("Imports: R.oo\n", file = "test/DESCRIPTION", append = TRUE)
writeLines(
"#' Check an argument
#'
#' Checks an argument.
#' #param ... Some arguments.
#' #return A value.
#' #export
check.arg <- function(...) 0",
"test/R/check.arg.R"
)
roxygenise("test")
Now the namespace contains the line S3method(check,arg).
check is an S3 generic in R.oo, so roxygen is trying to be smart and guessing that I want check.arg to be an S3 method. Unfortunately, these functions are unrelated, so I don't.
(To preempt suggestions that I just rename check.arg: this is legacy code written by others, and I've created a checkArg replacement, but I need to leave check.arg as a deprecated function for compatibility.)
As Mr Flick commented, appending the full function name to the roxygen line works correctly. If I change the line to:
#' #export check.arg
then the NAMESPACE file contains:
export(check.arg)
Use #method generic class and #export instead of #S3method. Take a look at this thread:
S3 method help (roxygen2)

Access package-wide variable from within an R6 class

I am currently packaging up an API wrapper in R and found myself in a scenario in which I need to access a package-wide variable from within an R6 class (as it'll be used for a simple string concatenation). Below you can find an exemplification of my class:
#' A class that will need a package-wide variable
#'
#' #export
MyClass <- R6::R6Class(
"MyClass",
public = list(
# This var is a concat between a package-wide variable and a str
base_url = paste0(.base_url, "me/", "endpoint"),
)
)
.base_url is declared in my zzz.R file in the following way:
.base_url <- "https://api.coolwebsite.com/v1/"
# Assign var to the environment
.onLoad <- function(libname, pkgname) {
assign('.base_url', .base_url, envir = parent.env(environment()))
}
Now, when building the package I receive the following error, I do believe there is something I don't fully grasp in the order of evaluation of files when loading a package.
Loading test
Error in paste0(.base_url, "me/", "endpoint") :
object '.base_url' not found
At the moment, the only way I've found to evaluate .base_url before MyClass is to "alter" evaluation order by declaring .base_url in a file that will be evaluated before zzz.R (like constants.R or anything that'll come earlier in alphabetical order).
How can I keep all my package-wide variables in zzz and avoid incurring in the error above?
Answering my own question here as no one has come up with an answer and it might be helpful to people facing the same issue.
Apparently there are two ways of overriding file order when a package gets attached (more on this here):
1. #include roxygen tag
Listing files a function might depend on using #include roxygen tag, will force to load those files before the function gets evaluated, making sure to have all the variables into the namespace at the time of function evaluation.
#' A class that will need a package-wide variable
#'
#' #include zzz.R
#'
#' #export
MyClass <- R6::R6Class(
# ... All those fancy class methods
)
This will be reflected by changes in the Collate section of your DESCRIPTION file.
2. Edit Collate section in DESCRIPTION file
If not using {roxygen} (but you really should) you can do things by hand and put zzz.R first in the Collate section of your DESCRIPTION file (right after Imports).

Package function set as S3method instead of a generic function [duplicate]

Since roxygen2 version 4.0.0, the #S3method tag has been deprecated in favour of using #export.
The package now tries to detect if a function is an S3 method, and automatically adds the line S3method(function,class) to the NAMESPACE file if it think it is one.
The problem is that if a function is not an S3 method but its name contains a . then roxygen sometimes makes a mistake and adds the line when it shouldn't.
Is there a way to tell roxygen that a function is not an S3 method?
As requested, here's a reproducible example.
I have a package that imports R.oo, with a function named check.arg.
library(roxygen2)
package.skeleton("test")
cat("Imports: R.oo\n", file = "test/DESCRIPTION", append = TRUE)
writeLines(
"#' Check an argument
#'
#' Checks an argument.
#' #param ... Some arguments.
#' #return A value.
#' #export
check.arg <- function(...) 0",
"test/R/check.arg.R"
)
roxygenise("test")
Now the namespace contains the line S3method(check,arg).
check is an S3 generic in R.oo, so roxygen is trying to be smart and guessing that I want check.arg to be an S3 method. Unfortunately, these functions are unrelated, so I don't.
(To preempt suggestions that I just rename check.arg: this is legacy code written by others, and I've created a checkArg replacement, but I need to leave check.arg as a deprecated function for compatibility.)
As Mr Flick commented, appending the full function name to the roxygen line works correctly. If I change the line to:
#' #export check.arg
then the NAMESPACE file contains:
export(check.arg)
Use #method generic class and #export instead of #S3method. Take a look at this thread:
S3 method help (roxygen2)

Control where method documentation goes for simple generic, while hiding from package index

I'm writing an R package and largely following Hadley's book on the topic. I'm running into a problem with documenting methods for simple generics like print, plot, head, and tail. When I use the #describeIn tag to control where the method documentation goes, I get the nice feature of them showing up in the help file for the main analysis function that returns an object of the given class. The problem is that these generics also show up in the package's index. If I add #keywords internal to the generics, then they are removed from the package's index, but so is the main analysis function (they are in the same .R file). If I document the generics in a separate .R file, then I can gain control over what is and is not in the package's index, but I have two issues: the main analysis function doesn't come first in the Usage section of the help file; and if add the #keywords internal for the generics, this removes the analysis function from the package index too, even though they are documented (in this instance) in separate files. The crux of the problem seems to be that #keywords internal applies to all functions in the given .R file, and maybe even any function referenced in #describeIn, while #describeIn is designed for documenting multiple functions in a given .R file.
For now, I have the analysis function and generics in the same .R file to control where the method documention goes and its ordering in the Usage section, but am not using #keywords internal and leaving the index cluttered.
Here's a rough sketch of an exported analysis function:
#' #inheritParams foo
#' #export
seats <- function(judgeit.object, ...) {
[...omitted...]
class(out.object) <- "judgeit.seats"
return(out.object)
}
And a generic:
#' #describeIn seats Print a \code{\link{seats}} output
#' #keywords internal
#' #export
print.judgeit.seats <- function(x,...) print(x$output,...)
I want the help file for ?seats to look like this:
seats(judgeit.object, ...)
## S3 method for class 'judgeit.seats'
print(x, ...)
## S3 method for class 'judgeit.seats'
head(x, ...)
## S3 method for class 'judgeit.seats'
tail(x, ...)
I do not want print.judgeit.seats, head.judgeit.seats, etc. to appear in the package index, because it quickly becomes very cluttered.
Unfortunately, I am not aware of any easy fix for what you are asking.
Tags and their effect
#export will make your function visible in the global environment. CRAN requires that you document any such functions that is not hidden (i.e. that starts with .).
If you use #describeIn or #rdname, an automatic alias is created. Any alias creates an entry in the index, but points to the same .Rd file. For example, adding
#' #name myfunction
#' #aliases foo foobar`
would create foo and foobar entries in the index, but refer to the myfunction.Rd documentation file. If you try to delete manually the \alias{} in the .Rd file, CRAN will complain.
#describeIn will list the functions in the order they appear in the .R files (if they are documented in multiple files, they are listed according to the alphabetical order of the .R file, then the order of appearance). Reordering your functions can give you what you want.
#keywords internal (along with #export, a title and a description) will have Roxygen create a .Rd file that can be accessed by the user using ?, but will not be visible in the index (if you have only the tags, Roxygen will not create a .Rd file and you will get a warning because your function is not documented).
If you have a #keywords internal in any of the functions calling #describeIn, that function will be masked from the index. This does not apply to all functions in a .R file, only those which are aliases.
#usage requires you to have an alias for each method documented. You can try using instead #section Usage:, but note sections are listed in alphabetical order and the spacing will be larger.
Workaround
If you document a NULL function, you can add the #param you want. and include a multiple lines #Section: Usage field to include (manually) the S3 methods with your comments. Give it a name such as #name Seats (it cannot be the name of the function, otherwise you have ?seats pointing to two different files).
Then, document your function seats with a different #name tag and a different title, and use #internal' to hide it from the user. Use \code{\link{seats}}` to refer to that documentation.
#' Seats
#' Description of the function
#' #param judgeit.object object
#' #param x object from seats
#' #param ... additional arguments
#' #name seats
#' #section Usage:
#' \preformatted{seats(judgeit.object, ...)
#' ## S3 method for class 'judgeit.seats'
#' print(x, ...)
#' ## S3 method for class 'judgeit.seats'
#' head(x, ...)
#' ## S3 method for class 'judgeit.seats'
#' tail(x, ...)}
NULL
#' Seats function
#' #name internal-function
#' #inheritParams seats
#' #export
#' #keywords internal
#' #seealso \code{\link{seats}}
seats <- function(judgeit.object, ...) {
[...omitted...]
class(out.object) <- "judgeit.seats"
return(out.object)
}
#' Print a \code{\link{seats}} output
#'
#' #inheritParams seats
#' #describeIn internal-function
#' #export
print.judgeit.seats <- function(x,...) print(x$output,...)
This way, the user calling ?seats will be pointed to the overall documentation.

roxygen2: Issue with exporting print method

I have updated to roxygen2 v4.0.0 and am now attempting to convert #S3method and #method commands to #export commands following the directions here. This seems to have worked well for all of my methods except for those related to print.
Here is a toy example that illustrates my problem (I understand the silliness of the example). Here is the .R file ...
#' Test.
#'
#' Test.
#'#aliases zzzTest print.zzzTest summary.zzzTest
#'#param v A numeric vector.
#'#param x A \code{zzzTest} object.
#'#param object A \code{zzzTest} object.
#'#param \dots Additional arguments for the S3 methods.
#'#return A \code{zzzTest} object.
#'#keywords manip
#'#examples
#'z <- zzzTest(runif(10,1,2))
#'print(z)
#'summary(z)
#'#rdname zzzTest
#'#export zzzTest
zzzTest <- function(v) {
tmp <- log(v)
class(tmp) <- "zzzTest"
}
#'#rdname zzzTest
#'#export
print.zzzTest <- function(x,...) { print(x, ...) }
#'#rdname zzzTest
#'#export
summary.zzzTest <- function(object,...) { summary(object) }
And this is the .Rd file that results from roxygenising ...
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{zzzTest}
\alias{print.zzzTest}
\alias{summary.zzzTest}
\alias{zzzTest}
\title{Test.}
\usage{
zzzTest(v)
print.zzzTest(x, ...)
\method{summary}{zzzTest}(object, ...)
}
\arguments{
\item{v}{A numeric vector.}
\item{x}{A \code{zzzTest} object.}
\item{object}{A \code{zzzTest} object.}
\item{\dots}{Additional arguments for the S3 methods.}
}
\value{
A \code{zzzTest} object.
}
\description{
Test.
}
\examples{
z <- zzzTest(runif(10,1,2))
print(z)
summary(z)
}
\keyword{manip}
My use of #export seems to work fine for the summary method (note the \method()), but not for the print method (note no \method() and only print.zzzTest). I was also successful using #export for several other methods in other .R files. My problems only seem to occur with the print method.
Can someone point out where I am going wrong? Thank you in advance for any help with this problem.
For what it is worth, I am using R 3.1.0, RStudio 0.98.501, and roxygen2 4.0.0.
UPDATE 1: There is an export(print.zzzTemp) but not an S3method(print,zzzTemp) in the namespace ... i.e., the same problem as ZNK (in the comments).
UPDATE 2: I copied the exact .R file into another package, roxygenized that package, and the .Rd file (and corresponding namespace) were created properly. This implies that I have some "switch" related to roxygen2 different between the two packages, but I can't seem to isolate the difference or find such a "switch" (I believe that I have only controlled roxygen through the project options in RStudio).
I have found a solution for my problem (In comments above) and it may work for yours. In The NEWS.md file for v3.0.0, it is mentioned that #method tag is not needed as roxygen2 will figure it out, but it's sill available in the rare case that roxygen2 cannot do so. My solution:
#' #method print myClass
#' #export
print.myClass <- function(x) print("myClass")
This gives me back the S3method(print, myClass) in my NAMESPACE file.
The 16th line of your code
#'#export zzzTest
needs to be
#'#export
as mentioned by Hadley in this link.
You might also need to remove the 2nd and 3rd instance of #export. And don't forget to do devtools::document() before building/checking.
The coding I outlined above worked for me until I added a #useDynLib pkg-name tag. Then I had to resort to the #method tag to get the desired NAMESPACE after devtools::document().

Resources