Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case when an R function returns an instance of an R6 class #9

Closed
jburos opened this issue Dec 8, 2023 · 2 comments
Closed

Case when an R function returns an instance of an R6 class #9

jburos opened this issue Dec 8, 2023 · 2 comments

Comments

@jburos
Copy link

jburos commented Dec 8, 2023

Hi,

I realize this library is a prototype, and not that actively maintained (per #5). However I'm really glad it's here as more and more R libraries use R6 classes and there is occasionally (frequently in my case) a need to port these to Python.

I have an example of a Model class (implemented as an R6 class) which has a method that returns a ModelFit class (separate R6 class). Each class works really well on its own. The problem comes when I try to use the ModelFit returned by a method implemented in the Model class (generated in R), rather than one I created in Python.

To be more concrete, let's say I run the following:

# pseudocode
data = pd.DataFrame()
mod = TSModel.new()
fit = mod.fit(data)

At this point, the Model object has a class rpy2_r6.r6b.TSModel whereas the ModelFit object has a class rpy2.robjects.environments.Environment:

In [73]: mod
Out[73]: <class 'rpy2_r6.r6b.TSModel'> at 0x142a3ed00

In [74]: fit
Out[74]: 
<rpy2.robjects.environments.Environment object at 0x143dc8100> [RTYPES.ENVSXP]
R classes: ('TSModelFit', 'R6')
n items: 20

Is there a way to turn this fit object into something of the rpy2_r6.r6b.TSModelFit class? Or, to do it analogously using the r6a formulation?

@jburos
Copy link
Author

jburos commented Dec 8, 2023

Ah, cool! I think I answered my own question!

from rpy2_r6 import r6a
fit2 = r6a.R6Instance(fit)

Then, I can run:

In [79]: fit2
Out[79]: R6Instance<TSModelFit>

@jburos jburos closed this as completed Dec 8, 2023
@lgautier
Copy link
Member

It is hard to be certain without more details about the implementation of your Python class TSModel. However, r6a and r6b are 2 different approaches to map R6 to Python. r6b is trying to dynamically create Python classes to match the R6 classes. What you worked out should be fine. The meta-programming in r6b might be trying be too clever for its own good.

If you followed this to get TSModel, the method fit was created dynamically by looking at the R6 class definition. However, there is currently no dynamic inference of the return type mapped to an rpy2_r6.r6b class (and I am not sure that it is possible to achieve this).

mod.fit() returns an Environment because R6 instances are R environment objects and r6b does not connect those dots yet.

If you want to stay with r6b all the way, the following might work:

# Assumes that the R6 class definition for `TSModelFit` is in `your_r_package`.
TSModelFit = r6b.R6DynamicClassGenerator(your_r_package.TSModelFit)

TSModelFit.__R6CLASS__(mod.fit)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants