Pyjnius: 1.2.1ではアクセスできないスーパークラスメソッド

作成日 2019年12月13日  ·  20コメント  ·  ソース: kivy/pyjnius

arraylist = autoclass("java.util.ArrayList")()
arraylist.iterator()
arraylist.stream()

これは1.2.0では機能しますが、1.2.1では機能しません。

AttributeError                            Traceback (most recent call last)
<ipython-input-7-5e67e1c90388> in <module>()
----> 1 arraylist.stream()

AttributeError: 'java.util.ArrayList' object has no attribute 'stream'

https://colab.research.google.com/drive/1F9u2jVQR5JFw_mk5Bq--VH1Ki91Xe5x3の再現可能なノートブック

stream()は、デフォルトとしてスーパーインターフェイスで定義されています。

また、java.util.Listを拡張するインターフェイスのメソッドへのアクセスにも問題がありました。

最も参考になるコメント

同じ問題があります。1.2.1ではスーパークラスメソッドにアクセスできませんが、1.2.0ではすべてが機能します。 これは非常に厄介なバグです。1.2.1リリースを削除するか、何らかの形で使用不可としてマークするのは理にかなっていると思いませんか?

全てのコメント20件

ローカルで再現できます。CIでも発生するかどうかを確認しましょう。時間があれば修正を探します。

CIは失敗しましたが、1.2.1でどのように破ったのかわかりません。 getDeclaredMethods()には、デフォルトの実装であるメソッドが含まれていないことがわかります。 (それらはクラスまたはそのスーパータイプで宣言されていません)。

https://blog.jooq.org/2018/03/28/correct-reflective-access-to-interface-default-methods-in-java-8-9-10/にいくつかの議論があり

すべてのインターフェイスとその親インターフェイスをウォークしてデフォルトのメソッドを追加するソリューションもありますか? (抽象メソッドを追加することもできますが、具体的なオブジェクトによって実装する必要があるため、これは不要に思えます)。

これは私が見つけた最も関連性の高いstackoverflowスレッドです: https

異なるJVM実装にはいくつかの違いがあるようです...

最初にjava.util.Collectionにキャストすると機能しますが、必須ではありません…:/

また、getMethodsの代わりにgetDeclaredMethodsを使用したためだと思います。すべてのインターフェイスをウォークしようとしましたが、どういうわけかgetInterfaces()でCollectionインターフェイスが見つかりませんでした…

うーん、これはうまくいくようです…理由は完全にはわかりません。
https://github.com/kivy/pyjnius/pull/466/files#diff -06f2b31838f083623d82353f734d644a

編集:ええと、セグメンテーション違反のために保存してください… https://github.com/kivy/pyjnius/runs/348651345
グリッチが発生した場合に備えて再実行を試み、ubuntu、python3.8、java10で再度クラッシュしました…
edit2:非常に混乱しています。3.8/ java10 / ubuntuを一緒に除外すると、現在のすべての組み合わせが機能し、次にjava 9と11を有効にして、3.7 / 11 / ubuntuで同じクラッシュが発生しました…少なくともopenjdk-11-jdkをインストールできます私のubuntuでpython3.7で簡単にテストできます……そしてそれは動作します。 grmbl。

https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=100815&view=logs&j=696704cc-6fef-57a3-ea36-f27779b8cd5e&t=06421391-4b55-523d-a804-5e1a5bfc1908
ちなみに、Linuxでのconda-forgeビルドにも1.2.1でいくつかのセグフォールトがあるようです。そのため、この問題は私の変更前に存在していた可能性があります。

パッチはコラボで私のために働きます

丁寧なバンプ。 これをマージするのは良いことです。 コードコメントを提案するコメントをdiffに追加しました。

これを長引かせて申し訳ありませんが、CIが通過するのを妨げるものが本当にわかりません。また、理解できないエラーを黙らせるためだけにターゲットの一部を無効にするのは好きではありません。 mこれからどのように進むべきかわからない。

これが#480による同時実行の問題であるかどうか疑問に思いましたが、pytestがデフォルトで同時実行されるとは思いません。

ローカルで再現してみましたが、#480の再現に失敗しました。 これが私のコマンドでした-そのDebianベースのイメージ:

docker run -i continuumio/anaconda3 /bin/bash <<EOF

cat /etc/os-release
apt-get update
mkdir /usr/share/man/man1
apt-get -y install openjdk-11-jdk-headless gcc ant

conda create -y -n pyjnius python=3.7.5
conda activate pyjnius

git clone https://github.com/kivy/pyjnius.git
cd pyjnius/
python -m pip install -U setuptools cython
python setup.py bdist_wheel
pip install --timeout=120 .[dev,ci]
ant all
cd tests/
CLASSPATH="../build/test-classes:../build/classes" PYTHONPATH=/opt/conda/envs/pyjnius/lib/python3.7/site-packages/ pytest -v
cd ../
git checkout -b issue_465 origin/issue_465

python setup.py bdist_wheel
pip install --timeout=120 .[dev,ci]
ant all
cd tests/
CLASSPATH="../build/test-classes:../build/classes" PYTHONPATH=/opt/conda/envs/pyjnius/lib/python3.7/site-packages/ pytest -v

EOF

すべてのテストはマスターとブランチで合格しました。

同じ問題があります。1.2.1ではスーパークラスメソッドにアクセスできませんが、1.2.0ではすべてが機能します。 これは非常に厄介なバグです。1.2.1リリースを削除するか、何らかの形で使用不可としてマークするのは理にかなっていると思いませんか?

これを長引かせて申し訳ありませんが、CIが通過するのを妨げるものが本当にわかりません。また、理解できないエラーを黙らせるためだけにターゲットの一部を無効にするのは好きではありません。 mこれからどのように進むべきかわからない。

CIテストを再実行することをお勧めしますか? これを絞り込むことはできますか?それはこのパッチの問題ですか、それとも以前のバージョンの問題ですか?

これに戻るには:

getDeclaredMethods()getMethods()混ぜることが答えだとは思いgetDeclaredMethods()getMethods()で十分です。

これに関する私のテストケースは次のとおりです。

 def test_super_interface(self):
        LinkedList = autoclass('java.util.LinkedList')
        words = LinkedList()
        words.add('hello')
        words.add('world')
        q = cast('java.util.Queue', words)
        self.assertEqual(2, q.size())
        self.assertIsNotNone(q.iterator())

    def test_super_object(self):
        LinkedList = autoclass('java.util.LinkedList')
        words = LinkedList()
        words.hashCode()

    def test_super_interface_object(self):
        LinkedList = autoclass('java.util.LinkedList')
        words = LinkedList()
        q = cast('java.util.Queue', words)
        q.hashCode()

getDeclaredMethods()のみを使用すると、さまざまな失敗が発生します。

getMethods()に関する私の唯一の問題は、 test_inheritance.pyが失敗することです。 これはごくわずかに問題があります-org.jnius.Childの静的newInstance() org.jnius.Parent newInstance()メソッドをオーバーライドします。 getMethods()は両方のnewInstance()メソッドをChild.newInstance()Parent.newInstance()を非表示にする必要があります-https://www.java67.com/2012/08/can-we-override-static-method-in-java.htmlを参照して

jshell> org.jnius.Child.newInstance()
$3 ==> org.jnius.Child<strong i="24">@506c589e</strong>

こんにちは@tshirtman私はあなたがgetMethods()をコミットしたのを見ます。 上記の追加のテストケースもお勧めします。
Child.newInstance()がParent.newInstance()を非表示にする静的メソッドを解決する方法がわかりませんでした。 autoclass()でクラスとインターフェイスの反復を並べ替える必要があると思います。ツリーをたどってクラスを取得してから、逆の順序で適用します。つまり、java.lang.Objectから始めます。

うーん、確かにこのテストを追加すると、現在java.util.Queueオートクラスとしてキャストされたオブジェクトにsize属性がないことがわかります。これは間違っています。
私はあなたの分析、逆ルックアップ、JavaMultipleMethodを作成する代わりに親メソッドを同一の署名に置き換えることに同意します。これは良い戦略のようです。

501はすべてのテストに合格しました。 この問題を閉じます。 (賞賛してください)。

保護されたフィールドはまだありません!

この行publicからprotectedすると、テストに失敗します。

プライベート/保護されたメソッド/フィールドを公開する必要があるかどうかについては、#500に関する議論があります。

私はそれが違うと思います、現在私たちはすべてを持っているはずです、そしてあなたの修正で、それはメソッドには当てはまるようですが、明らかにそれはフィールドには当てはまらない(そしておそらくそうではなかったのですか?)ので、最初に解決するのはバグだと思います、プライバシーのレベルに応じて、表示したいメソッド/フィールドのフィルタリングを許可するかどうか。 このバグはクローズされているので、その場合に新しいバグを開くのは理にかなっています。

メソッドには当てはまるようですが、フィールドには当てはまらないようです(おそらくそうではありませんでしたか?)

<1.2.1で動作したので、どのバージョンでも動作するはずがなかったとしても、> 1.2.1、<2.0でも動作すると思います。

このページは役に立ちましたか?
0 / 5 - 0 評価