Bug 151603 - ScriptForge library gives an error on rpy2py conversion
Summary: ScriptForge library gives an error on rpy2py conversion
Status: RESOLVED NOTABUG
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
7.3.6.2 release
Hardware: All Linux (All)
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: ScriptForge
  Show dependency treegraph
 
Reported: 2022-10-17 11:58 UTC by Paul Smith
Modified: 2024-02-08 12:21 UTC (History)
2 users (show)

See Also:
Crash report or crash signature:


Attachments
Error messages (102.68 KB, image/png)
2022-10-18 15:01 UTC, Paul Smith
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Smith 2022-10-17 11:58:55 UTC
Description:
When I use this ScriptForge script, I get the error below:

------------------------------
import numpy as np
from rpy2.robjects.packages import importr, data
rpart = importr('rpart')
datasets = importr('datasets')
base = importr('base')

def acertos_iris(args=None):
    iris = data(datasets).fetch('iris')['iris']
    model = rpart.rpart('Species ~ .', iris)
    preds = rpart.predict_rpart(model, iris, type='class') 
    nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
    erro = nacertos[0]/150
    doc = CreateScriptService("Calc")
    doc.setArray("~.A1", erro)

--------------------------------

The error:

---------------------------
Message: <class 'NotImplementedError'>: Conversion 'rpy2py' not defined for objects of type 'class 'rpy2.rinterface_lib.sexp.SexpEnvironment'>'

File "/usr/lib64/libreoffice/program/pythonscript.py", line 1057

Steps to Reproduce:
When I use this ScriptForge script, I get the error below:

------------------------------
import numpy as np
from rpy2.robjects.packages import importr, data
rpart = importr('rpart')
datasets = importr('datasets')
base = importr('base')

def acertos_iris(args=None):
    iris = data(datasets).fetch('iris')['iris']
    model = rpart.rpart('Species ~ .', iris)
    preds = rpart.predict_rpart(model, iris, type='class') 
    nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
    erro = nacertos[0]/150
    doc = CreateScriptService("Calc")
    doc.setArray("~.A1", erro)

--------------------------------

The error:

---------------------------
Message: <class 'NotImplementedError'>: Conversion 'rpy2py' not defined for objects of type 'class 'rpy2.rinterface_lib.sexp.SexpEnvironment'>'

File "/usr/lib64/libreoffice/program/pythonscript.py", line 1057

Actual Results:
The error.

Expected Results:
No error.


Reproducible: Always


User Profile Reset: No



Additional Info:
 .
Comment 1 Paul Smith 2022-10-17 12:44:50 UTC
This same error occurs even using a much shorter version of the code:

--------------------------------------- 
from scriptforge import CreateScriptService
from rpy2.robjects.packages import importr
rpart = importr('rpart')
    
def acertos_iris(args=None):
    doc = CreateScriptService("Calc")
    doc.setArray("~.A1", 4)
---------------------------------------
Comment 2 Rafael Lima 2022-10-17 22:32:30 UTC
Hi Paul, thanks for reporting.

Your bug does not seem to be related to ScriptForge itself, but rather to your Python environment.

What OS are you running? Is your LibreOffice installed via deb, flatpak, snap?

Also, run the following ultra-simplified script on your machine:

-------------------

from rpy2.robjects.packages import importr
rpart = importr('rpart')
    
def acertos_iris(args=None):
    print("")

--------------------

Let me know if it results in the same error.
Comment 3 Paul Smith 2022-10-18 09:31:55 UTC
Thanks, Rafael, for your answer!

Running your ultra-simplified code does not produce any error.

My operating system is Fedora Linux 36, and my LibreOffice installation is based on the packages (rpm) provided by Fedora distribution.
Comment 4 Rafael Lima 2022-10-18 12:28:17 UTC
(In reply to Paul Smith from comment #3)
> Running your ultra-simplified code does not produce any error.

Hi Paul! That's weird. I don't know how ScriptForge would interfere with another package.

@JPL do you have any idea of what might be happening here?
Comment 5 Jean-Pierre Ledure 2022-10-18 14:44:54 UTC
Message: <class 'NotImplementedError'>: Conversion 'rpy2py' not defined for objects of type 'class 'rpy2.rinterface_lib.sexp.SexpEnvironment'>'

Anyway, above message is not issued by ScriptForge. It is issued by pythonscript.py that does not recognize the passed object.

I would insert a
   print(erro)
Statement. If it not a tuple (of tuples) containing strings and numbers only, it cannot be stored in a Calc sheet.

Other question: usually Python errors provide the line number where the error occurred. Can we see the whole message ?
Comment 6 Paul Smith 2022-10-18 15:00:36 UTC
Thanks, Jean-Pierre!

I think the problem is not triggered by

'erro',

as the code in Comment 1 produces the same error and there is no variable 'erro'.

I am attaching the error report of LibreOffice as a screen-shot.
Comment 7 Paul Smith 2022-10-18 15:01:09 UTC
Created attachment 183120 [details]
Error messages
Comment 8 Jean-Pierre Ledure 2022-10-18 15:13:33 UTC
U don't see any mention of scriptforge.py in the stack of functions listed in the error message ?
Or is the message not complete ?
Comment 9 Paul Smith 2022-10-18 15:20:39 UTC
I am not sure whether the error message is or is not complete: I have shared a screen-shot of the *entire* error message LibreOffice spits out. Is there some other way to get the error message?
Comment 10 QA Administrators 2022-10-19 03:34:53 UTC Comment hidden (obsolete)
Comment 11 Rafael Lima 2022-11-02 14:58:42 UTC
Hi Paul, any updates about this issue?

Did you find any workaround to make the rpy2 library work with your code?

From the error message, it does not seem the issue is caused by ScriptForge, since none of entries in the message involve ScriptForge files.

What you could try is simply rewrite the code without ScriptForge and see if it works. Instead of using the SetArray method from ScriptForge, you could use the API directly:

doc = XSCRIPTCONTEXT.getDocument()
sheet = doc.CurrentController.ActiveSheet
' This gets cell A1 from the active sheet
cell = sheet.getCellByPosition(0, 0)
cell.setValue(erro)
Comment 12 Paul Smith 2022-11-02 19:43:09 UTC
Thanks, Rafael, for your message!

I have just tried the following script both from inside Calc and from a Python console. In Calc, I get the reported error all the same. However, in the Python console, no error at all.

---------------------------------------
[x@localhost python]$ pwd
/home/x/.config/libreoffice/4/user/Scripts/python
[x@localhost python]$ python
Python 3.10.7 (main, Sep  7 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import uno
>>> import numpy as np
>>> from rpy2.robjects.packages import importr, data
>>> rpart = importr('rpart')
>>> datasets = importr('datasets')
>>> base = importr('base')
>>> 
>>> def acertos_iris(args=None):
...     iris = data(datasets).fetch('iris')['iris']
...     model = rpart.rpart('Species ~ .', iris)
...     preds = rpart.predict_rpart(model, iris, type='class') 
...     nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
...     erro = nacertos[0]/150
...     doc = XSCRIPTCONTEXT.getDocument()
...     sheet = doc.CurrentController.ActiveSheet
...     cell = sheet.getCellByPosition(0, 0)
...     cell.setValue(erro)
...     doc.setArray("~.A1", erro)
... 
>>> 
---------------------------------------
Comment 13 Paul Smith 2022-11-02 19:48:57 UTC
In addition, Rafael, when I run the initial script (the one that uses ScriptForge) in the console, I get no error at all. It seems that the problem is when Calc itself runs the script.
Comment 14 Rafael Lima 2022-11-02 22:08:10 UTC
(In reply to Paul Smith from comment #13)
> In addition, Rafael, when I run the initial script (the one that uses
> ScriptForge) in the console, I get no error at all. It seems that the
> problem is when Calc itself runs the script.

You probably have different Python interpreters for each case.

In Calc the interpreter is probably different than the one you use in the shell. To verify that, use:

import sys
print(sys.executable)

Run the code above (1) from APSO Python shell and (2) from your terminal shell. You'll probably notice that the executable is different.
Comment 15 Jean-Pierre Ledure 2022-11-03 08:45:54 UTC
In:
def acertos_iris(args=None):
...     iris = data(datasets).fetch('iris')['iris']
...     model = rpart.rpart('Species ~ .', iris)
...     preds = rpart.predict_rpart(model, iris, type='class') 
...     nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
...     erro = nacertos[0]/150
...     doc = XSCRIPTCONTEXT.getDocument()
...     sheet = doc.CurrentController.ActiveSheet
...     cell = sheet.getCellByPosition(0, 0)
...     cell.setValue(erro)
...     doc.setArray("~.A1", erro)

only the last statement seems to invoke ScriptForge.
However, "doc" is a UNO object, not a ScriptForge Calc instance.

Can this explain the observed behaviours ?

Maybe, replace last statement with (not tested);
def acertos_iris(args=None):
...     iris = data(datasets).fetch('iris')['iris']
...     model = rpart.rpart('Species ~ .', iris)
...     preds = rpart.predict_rpart(model, iris, type='class') 
...     nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
...     erro = nacertos[0]/150
...     doc = XSCRIPTCONTEXT.getDocument()
...     sheet = doc.CurrentController.ActiveSheet
...     cell = sheet.getCellByPosition(0, 0)
...     cell.setValue(erro)
...     ui = CreateScriptService("UI")
...     doc2 = ui.GetDocument(doc)
...     doc2.setArray("~.A1", erro)
Comment 16 Paul Smith 2022-11-03 09:35:16 UTC
Thanks for your cooperation.

APSO console and my own Python console run the same Python binary:

/usr/bin/python3

I suspect that the error does not come from uno or ScriptForge, as when I run the following code on APSO console, I get the following error:

---------------------------------
>>> import uno
>>> import numpy as np
>>> from rpy2.robjects.packages import importr, data
>>> rpart = importr('rpart')
Traceback (most recent call last):
  File "/usr/lib64/python3.10/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 496, in importr
    pack = InstalledSTPackage(env, name,
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 203, in __init__
    self.__fill_rpy2r__(on_conflict=on_conflict)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 329, in __fill_rpy2r__
    (super(SignatureTranslatedPackage, self)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 264, in __fill_rpy2r__
    rpyobj = cv.rpy2py(riobj)
  File "/usr/lib64/python3.10/functools.py", line 889, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/conversion.py", line 252, in _rpy2py
    raise NotImplementedError(
NotImplementedError: Conversion 'rpy2py' not defined for objects of type '<class 'rpy2.rinterface_lib.sexp.SexpEnvironment'>'
>>> 
---------------------------------

Running this exact same code on my own Python console, no error is returned.
Comment 17 Werner Tietz 2022-11-07 09:42:59 UTC
may be this is related to  bug https://bugs.documentfoundation.org/show_bug.cgi?id=133123
Can you fix it by manually append the patch from comment 3 to your uno.py

btw. the following code runs with success on LO7.0.4.2 (with the mentioned patch):

```
import numpy as np
from rpy2.robjects.packages import importr, data
rpart = importr('rpart')
datasets = importr('datasets')
base = importr('base')

def acertos_iris(args=None):
    iris = data(datasets).fetch('iris')['iris']
    model = rpart.rpart('Species ~ .', iris)
    preds = rpart.predict_rpart(model, iris, type='class') 
    nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
    erro = nacertos[0]/150
    doc = XSCRIPTCONTEXT.getDocument()
    doc.CurrentSelection.Spreadsheet["A1"].Value = erro

```
as you can see "scriptforge" is irrelevant!
Comment 18 Paul Smith 2022-11-07 10:45:51 UTC
Thanks, Werner! Could you please give me some directions about how to apply the mentioned patch? I have never applied any patch! Thanks!
Comment 19 Werner Tietz 2022-11-07 11:30:29 UTC
Hallo Paul

your uno.py is probably located at /usr/lib/python3/dist-packages/uno.py 
otherwise you will find the path from python-console with:
import uno
print(uno.__file__)

open it with some text-editor and look around line ~365:
insert below:
        else:
            # How to create a module ??
            mod = pyuno.__class__(module)

the following:
        if mod is None:
            raise py_import_exc
Comment 20 Paul Smith 2022-11-07 11:42:07 UTC
Thanks, Werner, for your directions! Unfortunately, the pacth does not fix the reported problem:

--------------------------------------- 
>>> rpart = importr('rpart')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 496, in importr
    pack = InstalledSTPackage(env, name,
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 203, in __init__
    self.__fill_rpy2r__(on_conflict=on_conflict)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 329, in __fill_rpy2r__
    (super(SignatureTranslatedPackage, self)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/packages.py", line 264, in __fill_rpy2r__
    rpyobj = cv.rpy2py(riobj)
  File "/usr/lib64/python3.10/functools.py", line 889, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
  File "/home/x/.local/lib/python3.10/site-packages/rpy2/robjects/conversion.py", line 252, in _rpy2py
    raise NotImplementedError(
NotImplementedError: Conversion 'rpy2py' not defined for objects of type '<class 'rpy2.rinterface_lib.sexp.SexpEnvironment'>'
---------------------------------------
Comment 21 Werner Tietz 2022-11-07 12:57:37 UTC
ok - looks more like a broken rpy2-installation, for me it didnt work with `pip install rpy2 --user` but `sudo apt-get install python3-rpy2` did it.

try to unistall via `pip uninstall rpy2` and re_install via your fedora-packagemanager.
Comment 22 Paul Smith 2022-11-07 13:26:34 UTC
Excellent job, Werner! With using the system's package of rpy2, it works!

I am intrigued why with the user rpy2 package it worked when using a console other than the APSO one -- if the user installation of rpy2 were defective, it should also fail when not using APSO console, I guess.
Comment 23 Paul Smith 2022-11-07 13:33:25 UTC
Interestingly, Werner, when I run:

--------------------------------------- 
import numpy as np
from rpy2.robjects.packages import importr, data
rpart = importr('rpart')
datasets = importr('datasets')
base = importr('base')

def acertos_iris(args=None):
    iris = data(datasets).fetch('iris')['iris']
    model = rpart.rpart('Species ~ .', iris)
    preds = rpart.predict_rpart(model, iris, type='class') 
    nacertos = base.sum(base.diag(base.table(preds, iris.rx2(5))))
    erro = nacertos[0]/150
    doc = CreateScriptService("Calc")
    doc.setArray("~.A1", erro)
--------------------------------------- 

I get the following error:

---------------------------------------
Error during invoking function acertos_iris in module file:///home/x/.config/libreoffice/4/user/Scripts/python/bug.py (<class 'NameError'>: name 'CreateScriptService' is not defined
  File "/usr/lib64/libreoffice/program/pythonscript.py", line 915, in invoke
    ret = self.func( *args )
  File "/home/x/.config/libreoffice/4/user/Scripts/python/bug.py", line 13, in acertos_iris
    doc = CreateScriptService("Calc")
)
---------------------------------------
Comment 24 Paul Smith 2022-11-07 13:36:24 UTC
Please, Werner, just ignore my last comment: I had forgotten to add 

from scriptforge import CreateScriptService

to my script.

Now, it works!
Comment 25 Werner Tietz 2022-11-08 07:51:29 UTC
Hallo Paul
Don't rely too much on "Scriptforge", sooner or later you'll have to use the normal API anyway.

Assuming youre working from an already open calc-file, and you want to dump the data into current selected cell, then replace the last 2 lines in your function with:

```

    doc = XSCRIPTCONTEXT.getDocument()
    doc.CurrentSelection.Value = erro
```

may I suggest to use mri1.3.4.oxt from https://github.com/hanya/MRI/releases
Comment 26 Paul Smith 2022-11-08 11:55:53 UTC
Thanks a lot, Werner, for your help and for having suggested MRI to me, which seems to be a great tool!