Re: [R-pkg-devel] Conditionally register method with generic in other package

2018-01-22 Thread Joshua Ulrich
For posterity, the solution I employed did not register the method as
a formal S3 method.  Functionality in package B was unchanged as long
as package B was loaded and attached... which was good enough for my
purposes.

On Wed, Dec 6, 2017 at 6:45 AM, Joshua Ulrich  wrote:
> I have a feeling I know the answer to this question, but I'm asking
> with the hope that I learn something new.
>
> Package A defines a S3 generic function, "foo()".  Package B defines a
> S3 class "bar", and a foo.bar() method.  This method is not strictly
> necessary for the package to function, and package A has many
> dependencies.
>
> To avoid excessive dependencies, I would like to only register
> foo.bar() if package A is installed at the time package B is
> installed.  If package A is installed after package B, then warn the
> user when package B is loaded and/or attached, so they can re-install
> A and have foo.bar() registered correctly.
>
> I could figure out a way to do this manually, but doubt it would be
> CRAN-approved.  What is the recommended way to handle this situation?
> I've received one suggestion to split B into 2 packages: one without
> the method, and one with.  Are there other alternatives?
>
> Thanks,
> Josh
>
> --
> Joshua Ulrich  |  about.me/joshuaulrich
> FOSS Trading  |  www.fosstrading.com
> R/Finance 2018 | www.rinfinance.com



-- 
Joshua Ulrich  |  about.me/joshuaulrich
FOSS Trading  |  www.fosstrading.com
R/Finance 2018 | www.rinfinance.com

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] Conditionally register method with generic in other package

2017-12-07 Thread Hadley Wickham
We use this technique in a couple of places:
https://github.com/tidyverse/dbplyr/blob/6be777d8b23d588f19c98de52f4e58f16c2ef67e/R/zzz.R

Basic idea is to call registerS3method() manually, when needed - it's
just a little tricky because the suggested package may be loaded
either before or after your package.

Hadley

On Thu, Dec 7, 2017 at 1:45 AM, Joshua Ulrich  wrote:
> I have a feeling I know the answer to this question, but I'm asking
> with the hope that I learn something new.
>
> Package A defines a S3 generic function, "foo()".  Package B defines a
> S3 class "bar", and a foo.bar() method.  This method is not strictly
> necessary for the package to function, and package A has many
> dependencies.
>
> To avoid excessive dependencies, I would like to only register
> foo.bar() if package A is installed at the time package B is
> installed.  If package A is installed after package B, then warn the
> user when package B is loaded and/or attached, so they can re-install
> A and have foo.bar() registered correctly.
>
> I could figure out a way to do this manually, but doubt it would be
> CRAN-approved.  What is the recommended way to handle this situation?
> I've received one suggestion to split B into 2 packages: one without
> the method, and one with.  Are there other alternatives?
>
> Thanks,
> Josh
>
> --
> Joshua Ulrich  |  about.me/joshuaulrich
> FOSS Trading  |  www.fosstrading.com
> R/Finance 2018 | www.rinfinance.com
>
> __
> R-package-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-package-devel



-- 
http://hadley.nz

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] Conditionally register method with generic in other package

2017-12-07 Thread Hadley Wickham
On Thu, Dec 7, 2017 at 2:44 AM, Bill Denney  wrote:
>
>> On Dec 6, 2017, at 07:45, Joshua Ulrich  wrote:
>>
>> To avoid excessive dependencies, I would like to only register
>> foo.bar() if package A is installed at the time package B is
>> installed.  If package A is installed after package B, then warn the
>> user when package B is loaded and/or attached, so they can re-install
>> A and have foo.bar() registered correctly.
>
> One simple solution would be to wrap the instantiation of foo.bar in a 
> require test:
>
> if (require(A)) {
>   foo.bar <- function(...) {
> print("To be or not to be")
>   }
> } else {
>   message("To use the foo.bar function, please install package A.")
> }

I don't think that will work because the code will be executed at
build time, not package-load time.

Hadley

-- 
http://hadley.nz

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] Conditionally register method with generic in other package

2017-12-07 Thread Joshua Ulrich
Bill, Duncan,

Thanks for the replies.

On Wed, Dec 6, 2017 at 12:51 PM, Duncan Murdoch
 wrote:
> On 06/12/2017 8:44 AM, Bill Denney wrote:
>>
>>
>>> On Dec 6, 2017, at 07:45, Joshua Ulrich  wrote:
>>>
>>> To avoid excessive dependencies, I would like to only register
>>> foo.bar() if package A is installed at the time package B is
>>> installed.  If package A is installed after package B, then warn the
>>> user when package B is loaded and/or attached, so they can re-install
>>> A and have foo.bar() registered correctly.
>>
>>
>> One simple solution would be to wrap the instantiation of foo.bar in a
>> require test:
>>
>> if (require(A)) {
>>foo.bar <- function(...) {
>>  print("To be or not to be")
>>}
>> } else {
>>message("To use the foo.bar function, please install package A.")
>> }
>>
>
> It's usually better to use requireNamespace("A") instead of require("A")
> (and the quotes are needed in requireNamespace(), but optional in
> require()). That tries to load the package, but doesn't mess with the search
> list.
>
> But that'll likely cause warnings, unless the same condition is used in the
> NAMESPACE file where there should be an entry
>
> S3method(foo, bar)
>
> The thing is, I'm not sure if
>
> if (requireNamespace("A"))
>   S3method(foo, bar)
>
> is legal in a NAMESPACE file.
>
While perhaps not technically illegal, that doesn't work because you need

if (requireNamespace("A", quietly = TRUE)) {
  importFrom(A, foo)
  S3method(foo, bar)
}

to prevent an error about being able to find object 'foo' when loading
B's namespace.  But the importFrom() causes R CMD check to expect a
hard dependency on package A (and all its dependencies), which is what
I'm trying to avoid...


> Duncan Murdoch



-- 
Joshua Ulrich  |  about.me/joshuaulrich
FOSS Trading  |  www.fosstrading.com
R/Finance 2018 | www.rinfinance.com

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] Conditionally register method with generic in other package

2017-12-06 Thread Duncan Murdoch

On 06/12/2017 8:44 AM, Bill Denney wrote:



On Dec 6, 2017, at 07:45, Joshua Ulrich  wrote:

To avoid excessive dependencies, I would like to only register
foo.bar() if package A is installed at the time package B is
installed.  If package A is installed after package B, then warn the
user when package B is loaded and/or attached, so they can re-install
A and have foo.bar() registered correctly.


One simple solution would be to wrap the instantiation of foo.bar in a require 
test:

if (require(A)) {
   foo.bar <- function(...) {
 print("To be or not to be")
   }
} else {
   message("To use the foo.bar function, please install package A.")
}



It's usually better to use requireNamespace("A") instead of require("A") 
(and the quotes are needed in requireNamespace(), but optional in 
require()). That tries to load the package, but doesn't mess with the 
search list.


But that'll likely cause warnings, unless the same condition is used in 
the NAMESPACE file where there should be an entry


S3method(foo, bar)

The thing is, I'm not sure if

if (requireNamespace("A"))
  S3method(foo, bar)

is legal in a NAMESPACE file.

Duncan Murdoch

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] Conditionally register method with generic in other package

2017-12-06 Thread Bill Denney

> On Dec 6, 2017, at 07:45, Joshua Ulrich  wrote:
> 
> To avoid excessive dependencies, I would like to only register
> foo.bar() if package A is installed at the time package B is
> installed.  If package A is installed after package B, then warn the
> user when package B is loaded and/or attached, so they can re-install
> A and have foo.bar() registered correctly.

One simple solution would be to wrap the instantiation of foo.bar in a require 
test:

if (require(A)) {
  foo.bar <- function(...) {
print("To be or not to be")
  }
} else {
  message("To use the foo.bar function, please install package A.")
}

Thanks,

Bill
__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel