From renaud at mancala.cbio.uct.ac.za  Fri Jun 24 09:53:26 2011
From: renaud at mancala.cbio.uct.ac.za (Renaud Gaujoux)
Date: Fri, 24 Jun 2011 09:53:26 +0200
Subject: [Rd] Class not found when search in .onLoad
In-Reply-To: <4E036D6E.3000509@r-project.org>
References: <4E0321DE.2020601@cbio.uct.ac.za> <4E036D6E.3000509@r-project.org>
Message-ID: <4E044276.1070002@cbio.uct.ac.za>

Thank you John for your response.

Things are a little bit more complicated though. The inheritance checks 
are not only made in .onLoad, they are part of a class validity method, 
which is called in .onLoad because some objects from this class are 
created at this stage. Such objects can also be created at any moment, 
not in a call from .onLoad.

More or less briefly:
class 'A' is in fact a virtual class defined in the package's namespace, 
with the purpose of defining a common interface. While the package does 
provide some derived classes (i.e. defined within the namespace), users 
too must be able to define derived classes from 'A' (i.e. not defined 
within the namespace).
In another class from the namespace, the validity method checks that one 
of its character slot contains the name of a class that inherits from 
interface 'A'.

I was just expecting `isClass` and `extends` to also work in .onLoad 
without specifying the argument `where` (i.e. searching everywhere, 
starting by the package's namespace if called within a namespace). The 
argument `where` being there to allow finer search.

There is no argument pkgname to the validity method, to directly apply 
the work around. I guess I can always check the presence of the class in 
the some-how hard-coded namespace, and if it is not found there look for 
the class elsewhere:

#...
clref <- getClass('A', .Force=TRUE, where=THE.NAMESPACE)
cl <- getClass(name, .Force=TRUE, where=THE.NAMESPACE)
if( is.null(cl) )
     cl <- getClass(name, .Force=TRUE)

if( !extends(cl, clref) )
     return('invalid slot')
#...

I will use this, in last resort, although it feels strange as it will 
only be to deal with the case where objects are created within a call to 
.onLoad.

I am really interested in understanding why all this:

- what makes this call so different?
In my sample package, if I add a call `check.classes()` directly in 
script.R, the classes are correctly found when the installation sources 
the script prepare the package for lazy loading.
- why things seemed to work ok in R-2.12.1 at the installation loading 
check, but do not work when loading the package from an R session?

Could you please briefly give some explanations or pointers?

Thank you.

Bests,
Renaud

On 23/06/2011 18:44, John Chambers wrote:
> The workaround is to use the package's namespace, as you did.  That's 
> one of the reasons why pkgname is an argument to .onLoad().
>
> Depending on what you want to do, you can either use the namespace as 
> an argument where= or get the class definition from the namespace and 
> use it in place of the class name.
>
> A side advantage is that such checks work regardless of whether or not 
> the classes, etc. are exported from the package.  Also, on the remote 
> chance there is another class of the same name, the check works 
> unambiguously on your package's version.
>
> The relevant part of your script, modified accordingly, seems to work 
> as desired.
>
> John
>
> ############
> # script.R
> ############
>
> setClass('A', representation(data='numeric'))
>
> setClass('B', contains='A') # the argument is contains=
>
> check.classes <- function(where){
>
> message("isClass('A', where = where): ", methods::isClass('A', where = 
> where))
>
> message("isClass('B', where = where): ", methods::isClass('B', where = 
> where))
>
> classA <- getClass('A', where = where)
> classB <- getClass('B', where = where)
> message("extends(classB, classA): ", methods::extends(classB, classA))
> }
>
> .onLoad <- function(libname, pkgname=NULL){
> cat("\n## .onLoad ##\n")
> check.classes(asNamespace(pkgname))
> }
>
> .onAttach <- function(libname, pkgname){
> cat("\n## .onAttach ##\n")
> check.classes(asNamespace(pkgname))
> }
>
>
>
>
> On 6/23/11 4:22 AM, Renaud Gaujoux wrote:
>> Hi,
>>
>> I am facing with a strange behaviour of isClass and extends when these
>> are called in .onLoad in both R 2.12.1 and R 2.13.0. This is preventing
>> my package from doing some object initializations at a proper place
>> (i.e. in .onLoad).
>>
>> Suppose one defines two S4 classes in a package, and that one needs to
>> check the inheritance between these two when loading the package (e.g.
>> to validate slots in objects).
>> See package attached or code below (not sure attachments can go 
>> through).
>>
>> in R 2.13.0:
>> At the loading check after installation, the classes are not found by
>> `isClass` and `extends` when these are called in .onLoad, but are
>> correctly found when called in .onAttach.
>> However findClass correctly finds the class in both case, as well as
>> isClass if it is called with the argument
>> `where=asNamespace('<THE.PACKAGE.NAME>')`.
>> When the package is loaded from an open R session, the behaviour is the
>> same.
>>
>> in R 2.12.1:
>> the classes are correctly found by isClass and extends when these are
>> called in .onLoad or .onAttach, but only at installation (i.e. at the
>> loading check after R CMD INSTALL).
>> When the package is loaded from an open R session, one fails to find the
>> classes only in .onLoad while in .onAttach they are correctly found.
>>
>> This is really an issue as up to now I was using .onAttach to do my
>> checks and initialization, but it is not a wise thing as package that
>> would only need to import my package (load and not attach) will not get
>> internal objects properly initialized. All this should be done in
>> .onLoad, but I cannot do it due to this behaviour of `extends`.
>>
>> Can someone provide some explanations or work around.
>>
>> Thank you,
>> Renaud
>>
>>
>> ############
>> # script.R
>> ############
>>
>> setClass('A', representation(data='numeric'))
>>
>> setClass('B', contain='A')
>>
>> check.classes <- function(){
>>
>> a <- new('A')
>> b <- new('B')
>>
>> message("isClass('A'): ", methods::isClass('A'))
>> message("isClass('A') in namespace: ", methods::isClass('A',
>> where=asNamespace('anRpackage')))
>> message("findClass('A'): ")
>> print(methods::findClass('A'))
>>
>> message("isClass('B'): ", methods::isClass('B'))
>> message("isClass('B') in namespace: ", methods::isClass('B',
>> where=asNamespace('anRpackage')))
>> message("findClass('B'): ")
>> print(methods::findClass('B'))
>>
>> message("extends('B', 'A'): ", methods::extends('B', 'A'))
>> message("is(a, 'A'): ", is(a, 'A'))
>> message("inherits(a, 'A'): ", inherits(a, 'A'))
>> message("is(b, 'A'): ", is(b, 'A'))
>> }
>>
>> .onLoad <- function(libname, pkgname=NULL){
>> cat("\n## .onLoad ##\n")
>> check.classes()
>> }
>>
>> .onAttach <- function(libname, pkgname){
>> cat("\n## .onAttach ##\n")
>> check.classes()
>> }
>> ############
>>
>>
> ..............
>>
>> ###
>> UNIVERSITY OF CAPE TOWN
>> This e-mail is subject to the UCT ICT policies and e-mail disclaimer
>> published on our website at
>> http://www.uct.ac.za/about/policies/emaildisclaimer/ or obtainable from
>> +27 21 650 9111. This e-mail is intended only for the person(s) to whom
>> it is addressed. If the e-mail has reached you in error, please notify
>> the author. If you are not the intended recipient of the e-mail you may
>> not use, disclose, copy, redirect or print the content. If this e-mail
>> is not related to the business of UCT it is sent by the sender in the
>> sender's individual capacity.
>>
>> ###
>>
>>
>>
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel

 

###
UNIVERSITY OF CAPE TOWN 

This e-mail is subject to the UCT ICT policies and e-mai...{{dropped:5}}



[Rd] Class not found when search in .onLoad
Renaud Gaujoux