Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > CONSTRUCT - Python's way of Ruby's "alias_method"

Reply
Thread Tools

CONSTRUCT - Python's way of Ruby's "alias_method"

 
 
Slawomir Nowaczyk
Guest
Posts: n/a
 
      06-08-2006
On Thu, 08 Jun 2006 15:28:39 +0300
Ilias Lazaridis <> wrote:

#> *IMPORT*
#>
#> I would like to know, if this construct is valid, or if it can
#> result in problems (that I do not see as a newcomer):

The intricacies of import are far beyond me, but FWIW I do not see
anything wrong in this code.

#> Is there any way (beside a patch) to alter the behaviour to an
#> existing function.

You can just assign new function to the old name. There are a few
loops to hop through if you want to alter the behaviour of an existing
*method*... There is an example -- I do not know if a good one -- here:
http://aspn.activestate.com/ASPN/Coo...n/Recipe/52192

--
Best wishes,
Slawomir Nowaczyk
( )

Strange how people who don't even know their neighbors
are extremely curious to know if there's extra-terrestrial life.

 
Reply With Quote
 
 
 
 
Ilias Lazaridis
Guest
Posts: n/a
 
      06-09-2006
Maric Michaud wrote:
> Le Jeudi 08 Juin 2006 14:28, Ilias Lazaridis a écrit :
>> Another possibility is to enlink (hook?) the functionality into an
>> existent function
>>
>> Is there any way (beside a patch) to alter the behaviour to an existing
>> function. Is ther a python construct similar to the "alias_method" of Ruby:
>>

> No, there is no special construct to do this, but we do things very similar
> every day in Zope, it's called "monkey patch" :
>
> #patch_service.py
> from toto import service
>
> def my_impl(self, *args) :
> old_result = self._old_method(*args)
> # ...
> return new_result
>
> if not hasattr(service, '_old_method') :
> service._old_method = service.method
> service.method = my_impl
>
> once this file is imported, all future calls to "method" of service instances
> will use my_impl.


Ok, just a small problem when a _function_ is to be hooked.

Looking a the code in the debugger shows that the function "syncdb" is
correctly overridden. But when the code returns, "syncdb" has again it's
original value.

Can I import "syncdb" by reference instead by value, thus the change
'survives'?

#------------------------------------------------------------------------------

#syncdb_hook.py

from django.rework.evolve import evolvedb
from django.core.management import syncdb

def syncdb_new(*args) :
evolvedb()
syncdb_result = syncdb_old(*args)
return syncdb_result

if syncdb != syncdb_new:
syncdb_old = syncdb
syncdb = syncdb_new

..

--
http://lazaridis.com
 
Reply With Quote
 
 
 
 
Duncan Booth
Guest
Posts: n/a
 
      06-09-2006
Ilias Lazaridis wrote:

>> #patch_service.py
>> from toto import service
>>
>> def my_impl(self, *args) :
>> old_result = self._old_method(*args)
>> # ...
>> return new_result
>>
>> if not hasattr(service, '_old_method') :
>> service._old_method = service.method
>> service.method = my_impl
>>
>> once this file is imported, all future calls to "method" of service
>> instances will use my_impl.

>
> Ok, just a small problem when a _function_ is to be hooked.
>
> Looking a the code in the debugger shows that the function "syncdb" is
> correctly overridden. But when the code returns, "syncdb" has again
> it's original value.
>
> Can I import "syncdb" by reference instead by value, thus the change
> 'survives'?


The difference is that Maric imported the module. To make the change affect
the original model you have to access the function as an attribute of its
module, not by importing the function from the module.
>
> #----------------------------------------------------------------------
> --------
>
> #syncdb_hook.py
>
> from django.rework.evolve import evolvedb
> from django.core.management import syncdb

from django.core import management

>
> def syncdb_new(*args) :
> evolvedb()
> syncdb_result = syncdb_old(*args)
> return syncdb_result
>
> if syncdb != syncdb_new:
> syncdb_old = syncdb
> syncdb = syncdb_new
>

if management.syncdb != syncdb_new:
syncdb_old = management.syncdb
management.syncdb = syncdb_new

 
Reply With Quote
 
Ilias Lazaridis
Guest
Posts: n/a
 
      06-09-2006
Duncan Booth wrote:
> Ilias Lazaridis wrote:
>
>>> #patch_service.py
>>> from toto import service
>>>
>>> def my_impl(self, *args) :
>>> old_result = self._old_method(*args)
>>> # ...
>>> return new_result
>>>
>>> if not hasattr(service, '_old_method') :
>>> service._old_method = service.method
>>> service.method = my_impl
>>>
>>> once this file is imported, all future calls to "method" of service
>>> instances will use my_impl.

>> Ok, just a small problem when a _function_ is to be hooked.
>>
>> Looking a the code in the debugger shows that the function "syncdb" is
>> correctly overridden. But when the code returns, "syncdb" has again
>> it's original value.
>>
>> Can I import "syncdb" by reference instead by value, thus the change
>> 'survives'?

>
> The difference is that Maric imported the module. To make the change affect
> the original model you have to access the function as an attribute of its
> module, not by importing the function from the module.


ok, I understand.

the code below works, but has the limitation that I cannot import the
syncdb_hook within "django.core.management".

There is no way to import/get "syncdb" but mutable?

>> #syncdb_hook.py
>>
>> from django.rework.evolve import evolvedb
>> from django.core.management import syncdb

> from django.core import management
>
>> def syncdb_new(*args) :
>> evolvedb()
>> syncdb_result = syncdb_old(*args)
>> return syncdb_result
>>
>> if syncdb != syncdb_new:
>> syncdb_old = syncdb
>> syncdb = syncdb_new
>>

> if management.syncdb != syncdb_new:
> syncdb_old = management.syncdb
> management.syncdb = syncdb_new


works fine.

..

--
http://lazaridis.com
 
Reply With Quote
 
Ilias Lazaridis
Guest
Posts: n/a
 
      06-09-2006
Slawomir Nowaczyk wrote:
> On Thu, 08 Jun 2006 15:28:39 +0300
> Ilias Lazaridis <> wrote:
>
> #> *IMPORT*
> #>
> #> I would like to know, if this construct is valid, or if it can
> #> result in problems (that I do not see as a newcomer):
>
> The intricacies of import are far beyond me, but FWIW I do not see
> anything wrong in this code.
>
> #> Is there any way (beside a patch) to alter the behaviour to an
> #> existing function.
>
> You can just assign new function to the old name. There are a few
> loops to hop through if you want to alter the behaviour of an existing
> *method*... There is an example -- I do not know if a good one -- here:
> http://aspn.activestate.com/ASPN/Coo...n/Recipe/52192


This looks intresting, especially the comment, although I do not
understand what is meant by "creates a cycle in the object".

"
There is a Better Way to Add Methods To Classes, Moshe Zadka, 2001/03/15
This method creates a cycle in the object for no reason at all. The
following function will add any function to an instance in a cycle free way:

def add_method(self, method, name=None):
if name is None: name = method.func_name
class new(self.__class__): pass
setattr(new, name, method)
self.__class__ = new

Use as follows:

def pretty_str(self): pass

add_method(C(), pretty_str, '__str__')
"

--
http://lazaridis.com
 
Reply With Quote
 
Maric Michaud
Guest
Posts: n/a
 
      06-10-2006
Le Vendredi 09 Juin 2006 20:06, Ilias Lazaridis a écrit*:
> the code below works, but has the limitation that I cannot import the
> syncdb_hook within "django.core.management".


In [4]: from b import CONS

In [5]: import b

In [6]: b.CONS = 3

In [7]: CONS
Out[7]: 5

In [8]: from b import CONS

In [9]: CONS
Out[9]: 3

So, if you change one module name, a function or a class or a constant, you
must do it before it is imported, or you must reload modules using it. But
either are not always possible, and the later is not what you want to achieve
here as it will re-execute all initialisation code in those modules.

But think of that, a function is hopefully an object in python, hmmm :

In [1]: from temp import func

In [2]: func(5)
Out[2]: 5

In [3]: def g(s) : return s*2
...:

In [4]: func.func_code = g.func_code

In [5]: func(5)
Out[5]: 10

hey, that should work !

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 
Reply With Quote
 
Ilias Lazaridis
Guest
Posts: n/a
 
      06-10-2006
Maric Michaud wrote:
> Le Vendredi 09 Juin 2006 20:06, Ilias Lazaridis a écrit :
>> the code below works, but has the limitation that I cannot import the
>> syncdb_hook within "django.core.management".

>
> In [4]: from b import CONS
>
> In [5]: import b
>
> In [6]: b.CONS = 3
>
> In [7]: CONS
> Out[7]: 5
>
> In [8]: from b import CONS
>
> In [9]: CONS
> Out[9]: 3
>
> So, if you change one module name, a function or a class or a constant, you
> must do it before it is imported, or you must reload modules using it. But
> either are not always possible, and the later is not what you want to achieve
> here as it will re-execute all initialisation code in those modules.
>
> But think of that, a function is hopefully an object in python, hmmm :
>
> In [1]: from temp import func
>
> In [2]: func(5)
> Out[2]: 5
>
> In [3]: def g(s) : return s*2
> ...:
>
> In [4]: func.func_code = g.func_code
>
> In [5]: func(5)
> Out[5]: 10
>
> hey, that should work !


Great Construct! Much flexibility!

I'll try the implementation tomorrow.

-

The actual Versions of the hooks can be found here:

http://case.lazaridis.com/browser/dj..._hook.py?rev=7
http://case.lazaridis.com/browser/dj...hook.py?rev=13

This construct has helped to simplify nearly all simplification goals:

http://case.lazaridis.com/wiki/DjangoSchemaEvolution

..

--
http://lazaridis.com
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Behavior of if construct in switch case defualt construct. Mukesh C Programming 4 03-26-2010 12:38 PM
Any elegant way to construct the complete $k$-partite graph inPython? Paul Miller Python 6 11-24-2009 01:02 PM
Best way to construct an email - attach a html file and send a Python 6 08-23-2006 10:17 PM
Fastest way to construct this class Ninan C++ 2 04-18-2006 05:39 PM
way way way OT: MCNGP Announcement Neil MCSE 174 04-17-2006 05:55 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57