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

ij.py.from_java() returns scyjava.JavaList when input is java.util.ArrayList #100

Closed
carshadi opened this issue Feb 5, 2021 · 2 comments

Comments

@carshadi
Copy link

carshadi commented Feb 5, 2021

import imagej
ij = imagej.init(fiji_path, headless=False)
from scyjava import jimport
ArrayList = jimport('java.util.ArrayList')
arrayList = ArrayList()
print(type(arrayList))  # <java class 'java.util.ArrayList'>
print(type(ij.py.from_java(arrayList)))  # <class 'scyjava.JavaList'>

I'm not sure if this is the intended behavior, but the Usage.md states the return type should be a Python list

Running pyimagej 1.0.0 installed via conda-forge with openjdk 8.0.265 in a jupyter notebook

@ctrueden
Copy link
Member

ctrueden commented Feb 5, 2021

@carshadi Thanks for the report. It's confusing because when converting collections from Python to Java, data is copied. But when converting collections from Java to Python, the Java objects are wrapped using Python duck typing. So the type scyjava.JavaList is a Python class wrapping some Java object implementing java.util.List. Technically, the scyjava.JavaList object isn't a Python list, but it has all the same attributes and functions, which means that from a Pythonic perspective, it can be used as a list without issue (duck typing!).

That said, I believe there are a couple of gaps in the implemented functions of the Python collection wrappers. Not sure about JavaList, but I remember running into an issue recently with JavaSet, where some set functions from newer versions of Python were missing from the wrapper.

Now that we're using JPype, it's often the case that you don't need the scyjava.to_python a.k.a. ij.py.from_java function at all anymore, because JPype has a lot more magic than PyJNIus does. E.g.:

>>> import scyjava
>>> def process_list(l):
...   for i in l:
...     print(i + i)
... 
>>> process_list([1, 2, 3, 4])
2
4
6
8
>>> ArrayList = scyjava.jimport('java.util.ArrayList')
>>> jl = ArrayList([1, 2, 3, 4])
>>> process_list(jl)
2
4
6
8
>>> jl = ArrayList(['a', 'b', 'c', 'd'])
>>> process_list(jl)
aa
bb
cc
dd
>>> process_list(['a', 'b', 'c', 'd'])
aa
bb
cc
dd
>>> jl + jl
<java object 'java.util.ArrayList'>
>>> print(jl + jl)
[a, b, c, d, a, b, c, d]
>>> set(jl) - set(['b', 'd'])
{'a', 'c'}

If you really need a true list, you can do:

>>> list(jl)
['a', 'b', 'c', 'd']

So hopefully that's good enough for now!

Still, let us know if there are specific conversions you need that aren't working.

@ctrueden ctrueden closed this as completed Feb 5, 2021
@carshadi
Copy link
Author

carshadi commented Feb 5, 2021

thanks, this is helpful. casting with list() is just fine for us

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