I'm developing an R package which can optionally use third-party packages, as specified in the "suggests" field of the DESCRIPTION file. Functions which may optionally use the suggested third-party packages check for their availability via the requireNamespace function. These functions behave differently depending on the presence or not of the suggested packages.
While implementing tests for theses functions, I would like to test for the case where the optional packages are not present. My question is: is it possible to temporarily hide a namespace for testing purposes, such that the requireNamespace function returns FALSE when searching for it?
Related
Tl;dr
I have a complete NAMESPACE file for the package I am building. I want to execute all the importFrom(x,y) clauses in that file to get the set of necessary functions I use in the package. Is there an automated way to do that?
Full question
I'm currently working on building a package that in turns depends on a bunch of other packages. Think: both Hmisc and dplyr.
The other contributors to the package don't really like using devtools::build() every 5 minutes when they debug, which I can understand. They want to be able to toggle a dev_mode boolean which, when set to true, loads all dependencies and sources all scripts in the R/ and data-raw/ folders, so that all functions and data objects are loaded in memory. I don't necessarily think that's a perfectly clean solution, but they're technically my clients and it's a big help to them so please don't offer a frame challenge unless it's the most user-friendly solution imaginable.
The problem with this solution is that when I load two libraries whose namespace clash, functions in the package that would perfectly work otherwise start throwing errors. I thus need to improve my import system.
Thanks to thorough documentation (and the help of devtools::check()), my NAMESPACE is complete. I guess I could split it in pieces and eval() some well-chosen parts of it, but it sort of feels like I'm probably not the first person to encounter this difficulty. Is there an automated way to parse NAMESPACE and import the proper functions from the proper packages ?
Thanks !
I'm working on a fork of a package that depends upon the ReporteRs library.
However, this library has been deprecated by its owner for a few years, in favour of the officer and flextable libraries.
On of the main reasons for this depreciation is not to depend on rJava, which may cause installation problems and bugs.
In my package, how should I manage this case?
So far, my package was processing data to return a ReporteRs object. If I change my functions to return an officer object I would break backward compatibilty.
But if I don't, and keep old, ReporteRs returning function as legacy backward compatibilty functions, I have to keep ReporteRs in my dependencies and my package would be rJava-dependant.
Is there a win-win solution?
Here is what I would do:
Make your best attempt to re-implement your functions with the officer library, but keeping your old API. Make sure that you warn the users that these functions are deprecated. At the same time make new functions fully compliant with officer/flextable syntax. Note that you might change the behavior of the functions slightly (as in, not ensuring all parameters are properly evaluated), as long as they take the same parameters and return the same type of objects.
If that is really not possible, just add a compatibility warning to your old functions.
Create a transitional package version that you would keep around for a few weeks or months with both versions of these functions. If the package still needs to depend on rJava, tough luck.
Keep track of the packages that depend on your package. If there are not too many, you can contact their developers directly. Maybe the issue is not as serious as you think it is?
EDIT: As discussed above, you can make your dependency on ReportR conditional on the availability of ReportR. Then, you can put ReportR into the Suggests field of the DESCRIPTION file rather than Depends, and in the package you can use code like this:
if(requireNamespace("ReportR")) {
warning("This function is deprecated, better use MyNewFunction instead")
ReportR::whatever() ...
} else {
warning("To run this (deprecated) function, please install the ReportR package")
}
I am working on project and would like to use some function from R package. However, for my project requirements, I must modify these functions. Then used them for my project purpose only. Of course I would like to publish my work. The modification is on these functions only and I will use the new function in my project. So I will not change the package. So my question, shall I request the author permission for these modifications? I tried to modify these function because they are so closed to what I am doing. So, I just need to modify them. I am not plan to write a package.
As far as I know, if the pkg is on CRAN and if the Licence is GPL (>=2), your are allowed to copy and modify the content as long as the modified content is still in GPL and that you state that you modified the content. So you don't need to ask for the permission of the pkg creator.
A good practice would be to create your own package, calling it 'pkgextra' (where pkg is the name of the package) and stating in the DESCRIPTION that the package is built on top of another package e.g tidystringdist which is built on top of stringdist or ggExtra which is built on top of ggpot. Also, as R packages have a Dependencies component, you're clearly stating in the DESCRIPTION that you built your package depending on other packages.
To wrap up, no, you don't need the permission from the package author for as long as you distribute the created work with the same licence and that you state that you depend on this package.
I am starting to work on a family of R packages, all of which share substantial common code which is housed in its own package, lets call it myPackageUtilities. So I have several packages
myPackage1, myPackage2, etc...
All of these packages depend on every method in myPackageUtilities. For a real-world example, please see statnet on CRAN. The idea is that a future developer might create myPackageN, and instead of having to re-write/duplicate all of the supporting code, this future developer can simply use mypackageUtilities to get started.
There are complications:
1) Some of the code in mypackageUtilities is intended for end-users, and the rest is for internal development purposes. The end-user code needs to be properly documented using roxygen2. This code includes both S3 classes and generics, as well as various helper functions for the user.
2) The dependent packages (myPackage1, myPackage2, etc.) will likely extend S3 generics defined in myPackageUtilities.
My question is: What is the best way to assemble all of this? Here are two natural (but non-exhuastive) options:
Include mypackageUtilities under Imports: for all the dependent packages, and force users to separately load mypackageUtilities,
Include mypackageUtilities under Depends: for all the dependent packages, and be very selective about what is exported from mypackageUtilities so as to avoid cluttering the search path. All of the internal (non-exported) code will have to accessed via ::: in myPackage1, etc.
I originally asked a similar question over here, but quickly discovered the situation gets complicated quickly. For example:
If we use Imports: instead of Depends:, then any generics defined in mypackageUtilities aren't found by myPackage1, etc.
This makes using the generic templates provided by mypackageUtilities difficult/impossible, and almost defeats the purpose of this entire set-up.
If I define an S3 generic in mypackageUtilities and document it there, how can I have roxygen2 reference these docs in myPackage1?
Perhaps I am deeply misunderstanding how namespaces work, in which case this would be a great place to clear up my misunderstanding!
Welcome to the rabbit hole.
You may be pleasantly surprised to learn that you can import a function from myPackageUtilities into myPackage1 and then export it from myPackage1 to make it accessible from the global environment.
So, when you say that you have a function in myPackageUtilities that should be accessible by the end user when myPackage1 is loaded, this is what I would include in my documentation for fn_name in myPackage1
#' #importFrom myPackageUtilities fn_name
#' #export fn_name
(See https://github.com/hadley/dplyr/blob/master/R/utils.r for an example)
That still leaves the question of how to link to the original documentation. And I'm afraid I don't have a good answer for that. My current practice is to, essentially, copy the parameters documentation from the original source and then in my #details section write please see the documentation for \code{\link[myPackageUtilities]{fn_name}}
In the end, I still think your best bet is to export everything from myPackageUtilities that will ever get used outside of myPackageUtilities and do a combination import-export in each package where you want a function from myPackageUtilities to be accessible from the global environment.
In principle, I could keep these extensions not-exported, and this would also allow me to not-add redundant documentation for these already well-documented methods, while still also passing R CMD check myPackage without any reported WARNINGs.
What are some of the drawbacks, if any? Is this possibly recommended to keep extensions of basic methods compartmentalized within the package that defines them? Alternatively, will this make it more difficult for another package to depend on mine, if certain core method-extensions are not exported?
For example, if I don't document and don't export the following:
setMethod("show", "myPackageSpecialClass", function(object){ show(NA) })
I'm trying to flesh-out some of these finer details of best-practices with namespaces and base method extensions.
If you don't export the methods, then users (either at the command line or trying to use your classes and methods in their own package via imports) won't be able to use them -- your class will be displayed with the show,ANY-method.
You are not documenting the generic show, but rather the method appropriate for your class, show,myPackageSpecialClass-method. If in your NAMESPACE you
import(methods)
exportMethods(show)
(note that there is no way to export just some methods on the generic show) and provide no documentation, R CMD check will complain
* checking for missing documentation entries ... WARNING
Undocumented S4 methods:
generic 'show' and siglist 'myPackageSpecialClass'
All user-level objects in a package (including S4 classes and methods)
should have documentation entries.
See the chapter 'Writing R documentation files' in the 'Writing R
Extensions' manual.
Your example (I know it was not meant to be a serious show method :) ) is a good illustration for why methods might be documented -- explaining to the user why every time they try and display the object they get NA, when they were expecting some kind of description about the object.
One approach to documentation is to group methods with the class into a single Rd file, myPackageSpecialClass-class.Rd. This file would contain an alias
\alias{show,myPackageSpecialClass-method}
and a Usage
\S4method{show}{myPackageSpacialClass}(object)
This works so long as no fancy multiple dispatch is used, i.e., it is clear to which class a method applies. If the user asks for help with ?show, they are always pointed toward the methods package help page. For help on your methods / class, they'd need to ask for that specific type of help. There are several ways of doing this but my favorite is
class ? myPackageSpecialClass
method ? "show,myPackageSpecialClass"
This will not be intuitive to the average user; the (class|method) ? ... formulation is not widely used, and the specification of "generic,signature" requires a lot of understanding about how S4 works, including probably a visit to selectMethod(show, "myPackageSpecialClass") (because the method might be implemented on a class that myPackageSpecialClass inherits from) or showMethods(class="myPackageSpecialClass", where=getNamespace("myPackage")) (because you're wondering what you can do with myPackageSpecialClass).