sábado, 5 de dezembro de 2009

Erro __cmp__(x,y) requires y - Busca no ZOPE 2

O cenário é o seguinte: Você fez um ZSQL Method. Testou com um registro e estava tudo funcionando. Quando começou a testar com mais de um registro no banco de dados. Tudo parou de funcionar. Que lindo. O erro é algo parecido com:
mybrains.__cmp__(x,y) requires y to be a 'mybrains', not a 'ImplicitAcquirerWrapper'
ou
r.__cmp__(x,y) requires y to be a 'r', not a 'ImplicitAcquirerWrappe
Obviamente, as pessoas normais, como eu, não fazem nem idéia do que aconteceu, mas após pesquisar na Internet, descobri que é um BUG que afeta versões do Zope posteriores a 2.8.

O problema tem relação com a ordenação da busca (Order By). Então, você pode optar por não ordernar na consulta e fazer isso depois, via Python, mas não é uma boa idéia.
Que tal corrigir o problema? Não é difícil. Basta substituir uns códigos.

Acesse o diretório do seu ZOPE, não é da sua instância, é o diretório do ZOPE mesmo.
A partir desta pasta, encontre o arquivo abaixo:

lib/python/Shared/DC/ZRDB/Results.py

Você precisará fazer algumas modificações neste arquivo. Coisa simples, nada muito complexo. Procure pela linha
from Acquisition import Implicit
E substitua por:
from Acquisition import Implicit, aq_base
Depois de substituir este import, vamos ao próximo passo. Procure pela classe com a seguinte assinatura:
class r(Record, Implicit, brains, zbrains)
    'Result record class'
Procure pela ltrecho de código abaixo, deve estar um pouco logo em seguida a definição da classe "r":

%blocoHCodigoProgramacao%
r.__record_schema__=schema
         for k in Record.__dict__.keys():
-            if k[:2]=='__':
                 setattr(r,k,getattr(Record,k))

Substitua a terceira linha, que está sinalizada com um sinal de - pelo código a seguir:
if k[:2]=='__' and k!='__cmp__':
Preste atenção na endentação do arquivo. Se colocar errado, nada vai funcionar e você irá arrancar os cabelos.

Eu ainda executei uma outra modificação. Apesar de não saber se ela é realmente necessária, mas funcionou e não sou eu quem vai retirá-la de lá.

Procure o seguinte arquivo para alterar:
SOFTWARE_HOME/lib/python/Products/ZCatalog/CatalogBrains.py
Dentro dele, localize a classe AbstractCatalogBrain e adicione o método abaixo:
def __cmp__(self, other): return 0
Novamente: CUIDADO COM A ENDENTAÇÃO.

Depois disso, salve o arquivo, reinicie sua instância e pronto. O problema está corrigido.