[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

monkey patching with @classmethod

gentlestone

3/3/2010 11:57:00 AM

Hi, is there some well-known problems with class method monkey
patching?

I've got this error message:

unbound method get_pocet_neocislovanych() must be called with Pozemok
instance as first argument (got Subjekt instance instead)

The method is declared as:
@classmethod
@monkeypatch(Dokument)
def get_pocet_neocislovanych(cls, subjekt):
return cls.objects.filter(subjekt = subjekt, cislo__isnull =
True).count() # or pass, this line is not important

and the monkey patch decorator is declared as:
def monkeypatch(cls):
def decorator(func):
setattr(cls, func.__name__, func)
return func
return decorator

If I move the method to class declaration (whitout monkey patching),
everything is ok, but only if I've restarted the server.
3 Answers

Bruno Desthuilliers

3/3/2010 12:09:00 PM

0

gentlestone a écrit :
> Hi, is there some well-known problems with class method monkey
> patching?
>
> I've got this error message:
>
> unbound method get_pocet_neocislovanych() must be called with Pozemok
> instance as first argument (got Subjekt instance instead)

> The method is declared as:
> @classmethod
> @monkeypatch(Dokument)
> def get_pocet_neocislovanych(cls, subjekt):
> return cls.objects.filter(subjekt = subjekt, cislo__isnull =
> True).count() # or pass, this line is not important
>
> and the monkey patch decorator is declared as:
> def monkeypatch(cls):
> def decorator(func):
> setattr(cls, func.__name__, func)
> return func
> return decorator

The decorators are applied in order. So you first add the yet
undecorated function as an attribute of the class, then pass the
function to classmethod.

FWIW, this monkeypatch decorator is IMHO a plain waste of time. The
following code does the same thing and is (IMHO again) *much* more readable:

def get_pocet_neocislovanych(cls, subjekt):
return cls.objects.filter(
subjekt=subjekt,
cislo__isnull= True
).count() # or pass, this line is not important

Dokument.get_pocet_neocislovanych=@classmethod(get_pocet_neocislovanych)

Also, Django's BestPractice(tm) is to define such "query" methods on the
model's manager, not as a classmethod of the model.

My 2 cents

gentlestone

3/3/2010 12:12:00 PM

0

On 3. Mar., 12:57 h., gentlestone <tibor.b...@hotmail.com> wrote:
> Hi, is there some well-known problems with class method monkey
> patching?
>
> I've got this error message:
>
> unbound method get_pocet_neocislovanych() must be called with Pozemok
> instance as first argument (got Subjekt instance instead)
>
> The method is declared as:
> @classmethod
> @monkeypatch(Dokument)
> def get_pocet_neocislovanych(cls, subjekt):
>     return cls.objects.filter(subjekt = subjekt, cislo__isnull =
> True).count() # or pass, this line is not important
>
> and the monkey patch decorator is declared as:
> def monkeypatch(cls):
>     def decorator(func):
>         setattr(cls, func.__name__, func)
>         return func
>     return decorator
>
> If I move the method to class declaration (whitout monkey patching),
> everything is ok, but only if I've restarted the server.

for complexity, there is a code I call the method:

def _application_menu(request, subjekt, aplikacia_url_name):
return render_to_response('subjekty/aplikacia.html', {
'subjekt' : subjekt,
'aplikacia_url_name' : aplikacia_url_name,
'aplikacia_dictionary' :
aplikacia_dictionary(aplikacia_url_name),
'listy' : [
(dokument_url_name, dict(
get_verbose_name_plural =
dokument.get_verbose_name_plural(),
get_pocet_neocislovanych =
dokument.get_pocet_neocislovanych(subjekt),
get_pocet_celkom = dokument.get_pocet_celkom(subjekt),
)) for dokument_url_name, dokument in
aplikacia_dictionary(aplikacia_url_name)['listy']
],
}, context_instance = RequestContext(request))


unfortunately, sometimes it works, sometimes not, I cannot imagine the
reason, why and when it works and not - even whitout monkey patching

seems like some black magic

gentlestone

3/3/2010 1:45:00 PM

0

On 3. Mar., 13:09 h., Bruno Desthuilliers <bruno.
42.desthuilli...@websiteburo.invalid> wrote:
> gentlestone a écrit :
>
>
>
> > Hi, is there some well-known problems with class method monkey
> > patching?
>
> > I've got this error message:
>
> > unbound method get_pocet_neocislovanych() must be called with Pozemok
> > instance as first argument (got Subjekt instance instead)
> > The method is declared as:
> > @classmethod
> > @monkeypatch(Dokument)
> > def get_pocet_neocislovanych(cls, subjekt):
> >     return cls.objects.filter(subjekt = subjekt, cislo__isnull =
> > True).count() # or pass, this line is not important
>
> > and the monkey patch decorator is declared as:
> > def monkeypatch(cls):
> >     def decorator(func):
> >         setattr(cls, func.__name__, func)
> >         return func
> >     return decorator
>
> The decorators are applied in order. So you first add the yet
> undecorated function as an attribute of the class, then pass the
> function to classmethod.
>
> FWIW, this monkeypatch decorator is IMHO a plain waste of time. The
> following code does the same thing and is (IMHO again) *much* more readable:
>
> def get_pocet_neocislovanych(cls, subjekt):
>       return cls.objects.filter(
>          subjekt=subjekt,
>          cislo__isnull= True
>          ).count() # or pass, this line is not important
>
> Dokument.get_pocet_neocislovanych=@classmethod(get_pocet_neocislovanych)
>
> Also, Django's BestPractice(tm) is to define such "query" methods on the
>   model's manager, not as a classmethod of the model.
>
> My 2 cents

thx, I changed my definitions to manager style and have no more
problems

seems to be safe to use manager instead classmethod - do not know
why :-)