Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-08 Por tôpico Fernando Correa Neto
On 3/8/07, Rodrigo Senra <[EMAIL PROTECTED]> wrote:
>
>
>
>
>
>
>
>  [ Rafael Oliveira ]:
>
>  |A não ser que eu tenha como requisito registrar todas as modificações
>  |nos objetos ...
>
>  Outra idéia que surgiu agora é usar Workflows como "hook"
>  Ou seja, em cada edição do objeto o Workflow é notificado
>  e scripts (before/after) podem ser usados para rastrear
>  as mudanças de estado.
>
>  Eu nunca fiz isso, de forma que talvez Gurus tenham que
>  se manifestar aqui para dar coordenadas precisas.
>  Todavia, uma rápida busca na Internet (aka Google)
>  por "plone automatic workflow  transition triggered"
>  mostrou resultados promissores, como [1].

Uma idéia também é fazer isso usando eventos...notificam o seu event
handler, que por sua vez executa a lógica.
Mas advinha onde fica o hook?

at_post_edit_script

Dá uma olhada nesse pedaço de código retirado de [1].

from zope.event import notify

...

class Employee(ExtensibleSchemaSupport, BaseContent):

...

security.declarePrivate(permissions.View, 'at_post_create_script')
def at_post_create_script(self):
"""Notify that the employee has been saved.
"""
notify(EmployeeModifiedEvent(self))

security.declarePrivate(permissions.View, 'at_post_edit_script')
def at_post_edit_script(self):
"""Notify that the employee has been saved.
"""
notify(EmployeeModifiedEvent(self))

[]'s
Fernando

[1]  http://plone.org/documentation/tutorial/borg/sending-and-handling-events

>
>  """
>  You could also arrange to trigger workflow transitions during your
>  "edit" handling scripts;  this is what the old, now-deprecated
>  WorkflowMethod wrapper did.
>
>  Tres
>  """
>
>  Eu não sei qual é o "novo jeito", já que o mencionado pelo
>  Tres Seaver está deprecated ? Todavia, acho que é por aí.
>
>  [1] http://mail.zope.org/pipermail/zope-cmf/2004-August/021125.html
>
>  Abração,
>  Senra
>
>  -
>  Rodrigo Senra
>  GPr Sistemas
>  http://www.gpr.com.br
>


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-08 Por tôpico Rodrigo Senra

[ Rafael Oliveira ]:

|A não ser que eu tenha como requisito registrar todas as modificações
|nos objetos ...

Outra idéia que surgiu agora é usar Workflows como "hook"
Ou seja, em cada edição do objeto o Workflow é notificado
e scripts (before/after) podem ser usados para rastrear
as mudanças de estado.

Eu nunca fiz isso, de forma que talvez Gurus tenham que 
se manifestar aqui para dar coordenadas precisas.
Todavia, uma rápida busca na Internet (aka Google) 
por "plone automatic workflow  transition triggered" 
mostrou resultados promissores, como [1].

"""
You could also arrange to trigger workflow transitions during your 
"edit" handling scripts;  this is what the old, now-deprecated 
WorkflowMethod wrapper did.

Tres
"""

Eu não sei qual é o "novo jeito", já que o mencionado pelo
Tres Seaver está deprecated ? Todavia, acho que é por aí.


[1] http://mail.zope.org/pipermail/zope-cmf/2004-August/021125.html


Abração,
Senra

-
Rodrigo Senra
GPr Sistemas 
http://www.gpr.com.br


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object( ) sendo chamado várias vezes)

2007-03-07 Por tôpico Jean Rodrigo Ferri
Rafael Oliveira escreveu:
>>  Uma das lições aprendidas com isso (ainda que não fosse aplicado a
>>  PZP) é que hooks em *tudo* são os assassinos do desempenho.
>>  Por isso tome bastante cuidado, em geral hooks devem ser colocados
>>  em *poucos* objetos e mediante uma escolha cuidadosa de onde colocar.
> 
> A não ser que eu tenha como requisito registrar todas as modificações
> nos objetos ...

Talvez você possa tirar uma idéia de como implementar isso do código do 
PloneCollectorNG, que guarda um histórico de todas as alterações 
efetuadas nas configurações do coletor.

Abraço,

-- 
Jean Ferri


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-07 Por tôpico Rafael Oliveira
On 07 Mar 2007 07:16:38 -0800, Rodrigo Senra <[EMAIL PROTECTED]> wrote:
>
>  |Rodrigo Senra:
>
>  Só no momento da criação, ou em qualquer atualização de campo ?
>  Pelo que vc disse, me parece ser a segunda opção, ou seja
>  um hook em qualquer atualização de campo.

É isso mesmo !

>  Uma das lições aprendidas com isso (ainda que não fosse aplicado a
>  PZP) é que hooks em *tudo* são os assassinos do desempenho.
>  Por isso tome bastante cuidado, em geral hooks devem ser colocados
>  em *poucos* objetos e mediante uma escolha cuidadosa de onde colocar.

A não ser que eu tenha como requisito registrar todas as modificações
nos objetos ...

>  Feita essa advertência, uma forma seria no at_post_create_script()
>  da classe Base (da qual todos seus tipos herdam) vc coloca um
>  código reflexivo que inspeciona os campos (percorrendo o atributo
>  schema) e troca os getters/setters por wrappers que chamam o seu
>  método de hook (em pré-chain ou pós-chain) e chamam também o
>  getter/setter original. Não é trivial, mas também não é nada
>  do outro mundo.

É uma idéia interessante. Obrigado pela dica.

>
>  É preciso ter dois cuidados:
>
>  1) evitar recursão infinita - de dentro do hook, se vc tentar
>  (...)
> 2) O outro cuidado é não causar efeitos colaterais com os encantamentos
>do AT, CMF, ExtensionClass do Zope.

Ok !

>  |A primeira coisa que me veio a cabeça
>  |foi sobrescrever o __getattr__() das classes para interceptar as
>  |chamadas dos setters de todos os campos
>
>  Acho que *não* vai funcionar, pois o __getattr__ só é chamado se
>  os atributos *não estiverem previamente definidos*. Ou seja, só
>  funciona para atributos virtuais. Nessa linha seria melhor
>  usar __getattribute__, que é chamado até mesmo para atributos
>  *já definidos*.

Isso eu não sabia.

> Todavia, esta estratégia recai no problem de
>  "interceptar tudo" -> vai ficar uma carroça-de-boi-manco e vai
>  ser difícil escrever o código do hook.
>  Mas, se vc quiser ir por essa linha eu ficaria *contente*
>  se vc me provasse que eu estou errado a este respeito.
>  Toda a comunidade ganharia com isso.

Infelizmente eu não poderei testar nenhuma das soluções agora, porém
eu concordo que a solução que eu pensei inicialmente deve ser meio
complicada de implementar. A sua solução envolve menos magia negra do
Python :D

[]s

>
>  Abração,
>  Senra
>
>  -
>  Rodrigo Senra
>  GPr Sistemas
>  http://www.gpr.com.br

-- 
Rafael Bruno Cavalhero de Oliveira <[EMAIL PROTECTED]>
Paradigma 
http://rafaelbco.wordpress.com


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-07 Por tôpico Rodrigo Senra

|Rodrigo Senra:
|>
|>  Acho que vc pode criar um mutator para o campo.
|>  O  AT cria setters default para cada campo, mas estes
|>  podem ser sobrescritos por rotinas suas (bem como getters).

[ Rafael Oliveira ]:
|Essa solução funcionaria sim. Porém o meu cenário é um pouco pior (eu
|não deixei muito claro): eu gostaria de ter esse comportamento para
|todos os campos de vários tipos de objetos diferentes. Ou seja, eu
|quero registrar qualquer mudança em qualquer campo.

Só no momento da criação, ou em qualquer atualização de campo ?
Pelo que vc disse, me parece ser a segunda opção, ou seja 
um hook em qualquer atualização de campo.

Eu trabalhei em uma arquitetura genérica para isso [1] em 1997
(caraca já faz 10 anos) em parceria com o lendário Alexandre Oliva
(hoje secretário da FSF para a América Latina).
Uma das lições aprendidas com isso (ainda que não fosse aplicado a
PZP) é que hooks em *tudo* são os assassinos do desempenho.
Por isso tome bastante cuidado, em geral hooks devem ser colocados
em *poucos* objetos e mediante uma escolha cuidadosa de onde colocar.

Feita essa advertência, uma forma seria no at_post_create_script()
da classe Base (da qual todos seus tipos herdam) vc coloca um 
código reflexivo que inspeciona os campos (percorrendo o atributo 
schema) e troca os getters/setters por wrappers que chamam o seu
método de hook (em pré-chain ou pós-chain) e chamam também o
getter/setter original. Não é trivial, mas também não é nada
do outro mundo. 

É preciso ter dois cuidados:

  1) evitar recursão infinita - de dentro do hook, se vc tentar
 inspecionar o campo (que está sendo interceptado) tem que 
 fazê-lo de uma forma que não redispare o acesso ao getter/setter
 que por conseguinte irá disparar uma chamada recursiva  para
 o seu hook. Uma forma fácil de detctar isso é ver a CPU em 100% e
 a memória livre indo para o saco (se não estourar o maximum recursion
 depth antes) ;o)
  
   2) O outro cuidado é não causar efeitos colaterais com os encantamentos
  do AT, CMF, ExtensionClass do Zope. 



|Como eu não preciso dessa fucionalidade urgentemente eu não parei para
|pensar na solução mais elegante.

Touché, não sei se essa é elegante tampouco.

|A primeira coisa que me veio a cabeça
|foi sobrescrever o __getattr__() das classes para interceptar as
|chamadas dos setters de todos os campos 

Acho que *não* vai funcionar, pois o __getattr__ só é chamado se
os atributos *não estiverem previamente definidos*. Ou seja, só
funciona para atributos virtuais. Nessa linha seria melhor
usar __getattribute__, que é chamado até mesmo para atributos
*já definidos*. Todavia, esta estratégia recai no problem de
"interceptar tudo" -> vai ficar uma carroça-de-boi-manco e vai
ser difícil escrever o código do hook. 
Mas, se vc quiser ir por essa linha eu ficaria *contente* 
se vc me provasse que eu estou errado a este respeito.
Toda a comunidade ganharia com isso.

[1] http://www.lsd.ic.unicamp.br/~oliva/guarana/

Abração,
Senra

-
Rodrigo Senra
GPr Sistemas 
http://www.gpr.com.br


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-06 Por tôpico Rafael Oliveira
On 3/6/07, Rodrigo Senra <[EMAIL PROTECTED]> wrote:
>
>  [ Rafael Oliveira ]:
>
>  |2. A funcionalidade que eu procurava era de ter um gatilho ativado a
>  |cada vez que um campo de um objeto fosse alterado, mesmo que isso não
>  |acontecesse através da interface web. Por exemplo, se em algum lugar
>  |eu executasse " obj.setMeuField('meuvalor')" eu queria que um método
>  |fosse chamado. Pelo o que eu verifiquei nem o index_object do meu
>  |índice nem o at_post_edit_script são chamados nessa situação.
>  |
>  |Alguma idéia ?
>
>  Acho que vc pode criar um mutator para o campo.
>  O  AT cria setters default para cada campo, mas estes
>  podem ser sobrescritos por rotinas suas (bem como getters).

Essa solução funcionaria sim. Porém o meu cenário é um pouco pior (eu
não deixei muito claro): eu gostaria de ter esse comportamento para
todos os campos de vários tipos de objetos diferentes. Ou seja, eu
quero registrar qualquer mudança em qualquer campo.

Como eu não preciso dessa fucionalidade urgentemente eu não parei para
pensar na solução mais elegante. A primeira coisa que me veio a cabeça
foi sobrescrever o __getattr__() das classes para interceptar as
chamadas dos setters de todos os campos [1] (por exemplo, todos os
métodos cujos nomes começam com "set") e aí ativar o meu gatilho.

Se alguém tiver alguma sugestão eu agradeço !


[1] Essa idéia foi inspirada na classe ServerProxy do módulo xmlrpclib
da biblioteca padrão do Python 2.4.


>
>  Abração,
>  Senra
>
>  -
>  Rodrigo Senra
>  GPr Sistemas
>  http://www.gpr.com.br
>




-- 
Rafael Bruno Cavalhero de Oliveira <[EMAIL PROTECTED]>
Paradigma 
http://rafaelbco.wordpress.com


Re: [zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-06 Por tôpico Rodrigo Senra

[ Rafael Oliveira ]:

  |Olá Rodrigo,
|
|obrigado pela dica, ela me levou a outras questões:
|
|1. Continuo achando estranho o método index_object() ser chamado várias
|vezes. Acabei de fazer um teste onde ele é chamado 20 vezes durante a
|criação de um objeto.

Eu já vi isso acontecer. Simplesmente acho que "por segurança/simplicidade"
este método é chamado *muito* mais vezes (não sei o quanto do número 20
é influência do seu código ou das entranhas do CMF/Plone) do que seria
necessário. Consertar isso já é outra história, espero que em um 
refactor do CMF/Plone isso seja melhorado (não está no meu TODO ;o).


|2. A funcionalidade que eu procurava era de ter um gatilho ativado a
|cada vez que um campo de um objeto fosse alterado, mesmo que isso não
|acontecesse através da interface web. Por exemplo, se em algum lugar
|eu executasse " obj.setMeuField('meuvalor')" eu queria que um método
|fosse chamado. Pelo o que eu verifiquei nem o index_object do meu
|índice nem o at_post_edit_script são chamados nessa situação.
|
|Alguma idéia ?

Acho que vc pode criar um mutator para o campo.
O  AT cria setters default para cada campo, mas estes
podem ser sobrescritos por rotinas suas (bem como getters).

Abração,
Senra

-
Rodrigo Senra
GPr Sistemas 
http://www.gpr.com.br


[zope-pt] Chamar um método quando algum campo for alterado (Era: index_object() sendo chamado várias vezes)

2007-03-05 Por tôpico Rafael Oliveira

Olá Rodrigo,

obrigado pela dica, ela me levou a outras questões:

1. Continuo achando estranho o método index_object() ser chamado várias
vezes. Acabei de fazer um teste onde ele é chamado 20 vezes durante a
criação de um objeto.

2. A funcionalidade que eu procurava era de ter um gatilho ativado a cada
vez que um campo de um objeto fosse alterado, mesmo que isso não acontecesse
através da interface web. Por exemplo, se em algum lugar eu executasse "
obj.setMeuField('meuvalor')" eu queria que um método fosse chamado. Pelo o
que eu verifiquei nem o index_object do meu índice nem o at_post_edit_script
são chamados nessa situação.

Alguma idéia ?

[]s

On 3/4/07, Rodrigo Castardo <[EMAIL PROTECTED]> wrote:


  Opa Rafael!

se uq tu precisa eh um gatilho apos a criação de um objeto vc pode usar um
metodo:

at_post_create_script

e se por acaso precisar de outro na edicao, usa este metodo aqui:

at_post_edit_script

[]'s!


On 3/4/07, Rafael Oliveira <[EMAIL PROTECTED]> wrote:
>
>   Olá,
>
> estou tendo este "problema" na versão Zope 2.9.4/Plone 2.1.3/Python
> 2.4 (não testei em outras).
>
> Eu tenho uma classe que implementa um índice, declarada assim: [1]. O
> que acontece é que quando um objeto é criado no site, o método
> index_object() é chamado repetidas vezes, numa quantidade de vezes que
> varia de acordo com o tipo do objeto.
>
> Qual é a explicação para esse comportamento ? Há alguma forma de eu
> fazer o método index_object() ser chamado apenas uma vez no fim da
> criação do objeto ? Ou pelo menos reduzir o número de chamadas ?
>
> [1]
> class CBSyncIndex(Persistent, Implicit, SimpleItem):
> __implements__ = (PluggableIndex.PluggableIndexInterface,)
> meta_type = "CBSyncIndex"
> manage_options = (
> {'label': 'Settings',
> 'action': 'manage_main',
> 'help': ('CBSyncIndex', 'CBSyncIndex_Settings.stx')},
> )
> query_options = ["query"]
> # (...)
> def index_object(self, documentId, obj, threshold = None):
> #(...)
>
> def manage_addCBSyncIndex(self, id, extra = None, REQUEST = None,
> RESPONSE = None, URL3 = None):
> return self.manage_addIndex(id, 'CBSyncIndex', extra = extra,
> REQUEST = REQUEST, RESPONSE = RESPONSE, URL1 = URL3)
>
> []s
> --
> Rafael Bruno Cavalhero de Oliveira
> Paradigma 
> <[EMAIL PROTECTED] > < [EMAIL 
PROTECTED]
> >
> MSN: [EMAIL PROTECTED]  | ICQ: 26240428
>



--
Castardo
ThreePointsWeb
[EMAIL PROTECTED]
+55 61 8166-4109

 





--
Rafael Bruno Cavalhero de Oliveira
Paradigma 
<[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
MSN: [EMAIL PROTECTED] | ICQ: 26240428