Pyjnius: métodos da superclasse não acessíveis em 1.2.1

Criado em 13 dez. 2019  ·  20Comentários  ·  Fonte: kivy/pyjnius

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

Isso funciona para 1.2.0, mas não para 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'

Caderno reproduzível em https://colab.research.google.com/drive/1F9u2jVQR5JFw_mk5Bq--VH1Ki91Xe5x3

stream () é definido na superinterface como padrão.

Também tivemos problemas ao acessar métodos em interfaces que estendiam java.util.List.

Comentários muito úteis

Observo o mesmo problema, os métodos da superclasse não são acessíveis no 1.2.1, mas tudo funciona no 1.2.0. Este é um bug bastante desagradável, você não acha que faz sentido remover a versão 1.2.1 ou de alguma forma marcá-lo como inutilizável?

Todos 20 comentários

Posso reproduzir localmente, vamos ver se acontece também na CI, vou procurar um conserto quando tiver tempo.

O CI falhou, mas não consigo ver como o quebramos no 1.2.1. Posso ver que getDeclaredMethods () não inclui métodos que são implementações padrão. (Eles não são declarados na classe ou em seus supertipos).

Há alguma discussão em https://blog.jooq.org/2018/03/28/correct-reflective-access-to-interface-default-methods-in-java-8-9-10/ - Eu não _penso_ isso é relevante.

A solução também é percorrer todas as interfaces e suas interfaces pai adicionando métodos padrão? (Poderíamos adicionar os métodos abstratos, mas isso parece supérfluo, pois eles devem ser implementados pelo objeto concreto).

Este é o thread stackoverflow mais relevante que encontrei: https://stackoverflow.com/questions/28400408/what-is-the-new-way-of-getting-all-methods-of-a-class-including-inherited- defau

parece que pode haver algumas diferenças em diferentes implementações JVM ...

Funciona se eu lançar para java.util.Collection primeiro, mas não deve ser necessário ...: /

Eu também acho que é por causa do uso de getDeclaredMethods em vez de getMethods, eu tentei percorrer todas as interfaces, mas de alguma forma não encontrei a interface Collection em getInterfaces () ...

hm, isso parece funcionar ... não tenho certeza do porquê.
https://github.com/kivy/pyjnius/pull/466/files#diff -06f2b31838f083623d82353f734d644a

editar: uh, salve para um segfault… https://github.com/kivy/pyjnius/runs/348651345
tentei executar novamente caso fosse uma falha, travou novamente no ubuntu, python3.8, java 10 ...
edit2: muito confuso, todas as combinações atuais funcionaram quando excluí 3.8 / java10 / ubuntu juntos, depois habilitei o java 9 e 11 e tive o mesmo travamento com 3.7 / 11 / ubuntu ... bem, pelo menos posso instalar o openjdk-11-jdk no meu ubuntu e teste com python3.7 facilmente…… e funciona. 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-5e1a5bfc19
incindentalmente, parece que o conda-forge build no linux também tem alguns segfaults no 1.2.1, então o problema pode estar presente antes da minha mudança.

patch funciona para mim na colaboração

colisão educada. Seria bom mesclar este aqui. Eu adicionei um comentário ao diff sugerindo um comentário de código.

Desculpe por deixar isso demorar, eu realmente não tenho ideia do que impede o CI de passar, e eu realmente não gosto de desativar parte dos alvos apenas para silenciar um erro incompreensível, eu concordo que deixar este bitrot não é melhor, mas eu ' Não tenho certeza de como ir em frente com isso.

Eu me perguntei se esse era um problema de simultaneidade de acordo com o # 480, mas não acho que o pytest seja simultâneo por padrão.

Tentei reproduzir localmente, mas não consegui reproduzir # 480. Aqui estava meu comando - é uma imagem baseada em 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

Todos os testes foram aprovados no mestre e na filial.

Observo o mesmo problema, os métodos da superclasse não são acessíveis no 1.2.1, mas tudo funciona no 1.2.0. Este é um bug bastante desagradável, você não acha que faz sentido remover a versão 1.2.1 ou de alguma forma marcá-lo como inutilizável?

Desculpe por deixar isso demorar, eu realmente não tenho ideia do que impede o CI de passar, e eu realmente não gosto de desativar parte dos alvos apenas para silenciar um erro incompreensível, eu concordo que deixar este bitrot não é melhor, mas eu ' Não tenho certeza de como ir em frente com isso.

Posso sugerir uma nova execução dos testes de CI? Podemos tentar reduzir isso - é um problema neste patch ou um problema com uma versão anterior?

Para voltar a isso:

Não acho que misturar getDeclaredMethods() e getMethods() seja a resposta. getMethods() é suficiente.

Meus casos de teste para isso são:

 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()

Vários falham quando usamos apenas getDeclaredMethods ().

Meu único problema com getMethods() é que test_inheritance.py falha. Isso é apenas marginalmente problemático - o método estático newInstance() org.jnius.Child substitui o método org.jnius.Parent newInstance() . O que acontece é que getMethods() vê os dois métodos newInstance() , então constrói um JavaMultipleMethod. Isso está errado: Child.newInstance() deve ocultar Parent.newInstance() - consulte https://www.java67.com/2012/08/can-we-override-static-method-in-java.html. Eu também verifiquei isso usando Jshell:

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

Olá, @tshirtman , vejo que você comprometeu getMethods (). Eu recomendaria os casos de teste adicionais acima também.
Eu não tinha certeza de como resolver o método estático que esconde que Child.newInstance () deve ocultar Parent.newInstance (). Acho que você teria que reordenar a iteração de classes e interfaces em autoclass () - percorrer a árvore para obter as classes e aplicá-las na ordem inversa, ou seja, começando em java.lang.Object.

hm, de fato adicionar este teste mostra que atualmente o objeto lançado como um java.util.Queue autoclass não tem um atributo size , que está errado.
Eu concordo com sua análise, pesquisa reversa, substituição de métodos pais por assinatura idêntica em vez de fazer um JavaMultipleMethod, que parece uma boa estratégia.

501 passou em todos os testes. Fechando esta questão. (Louvado seja).

Campos protegidos ainda faltando!

Alterar esta linha de public para protected falha no teste.

Há uma discussão em # 500 sobre se métodos / campos privados / protegidos devem ser expostos.

Acho que é diferente, atualmente devemos ter tudo e, com sua correção, parece ser verdadeiro para métodos, mas aparentemente não é (e possivelmente nunca foi?) verdadeiro para campos, então acho que é um bug para resolver primeiro , se decidimos permitir a filtragem dos métodos / campos que desejamos ver, dependendo de seu nível de privacidade. Como esse bug está fechado, faz sentido abrir um novo para esse caso.

parece ser verdadeiro para métodos, mas aparentemente não é (e possivelmente nunca foi?) verdadeiro para campos

Funcionou para <1.2.1, então eu esperaria que funcionasse em> 1.2.1, <2.0 também, mesmo que não devesse ter funcionado para nenhuma versão.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Thrameos picture Thrameos  ·  27Comentários

hanslovsky picture hanslovsky  ·  3Comentários

Hukuta picture Hukuta  ·  5Comentários

ignertic picture ignertic  ·  4Comentários

stania picture stania  ·  6Comentários