From: John Nagle on
Is it possible to override "__setattr__" of a module? I
want to capture changes to global variables for debug purposes.

None of the following seem to have any effect.

modu.__setattr__ = myfn

setattr(modu, "__setattr__", myfn)

delattr(modu, "__setattr__")

John Nagle
From: Michele Simionato on
On Jun 16, 4:43 am, John Nagle <na...(a)animats.com> wrote:
>    Is it possible to override "__setattr__" of a module?  I
> want to capture changes to global variables for debug purposes.
>
>    None of the following seem to have any effect.
>
>         modu.__setattr__ = myfn
>
>         setattr(modu, "__setattr__", myfn)
>
>         delattr(modu, "__setattr__")
>
>                                 John Nagle

There is a dirty trick which involves fiddling with sys.modules.
For instance:

$ cat x.py
import sys

class FakeModule(object):
def __init__(self, dic):
vars(self).update(dic)
def __setattr__(self, name, value):
print "setting %s=%s" % (name, value)
object.__setattr__(self, name, value)

a = 1
def f():
print 'called f'

sys.modules[__name__] = FakeModule(globals())

Here is an ipython session:

In [1]: import x

In [2]: x.a
Out[2]: 1

In [3]: x.f
Out[3]: <function f at 0x93f5614>

In [4]: x.f()
called f

In [5]: x.a=2
setting a=2

In [6]: x.a
Out[6]: 2

From: John Nagle on
On 6/15/2010 8:34 PM, Michele Simionato wrote:
> On Jun 16, 4:43 am, John Nagle<na...(a)animats.com> wrote:
>> Is it possible to override "__setattr__" of a module? I
>> want to capture changes to global variables for debug purposes.
>>
>> None of the following seem to have any effect.
>>
>> modu.__setattr__ = myfn
>>
>> setattr(modu, "__setattr__", myfn)
>>
>> delattr(modu, "__setattr__")
>>
>> John Nagle
>
> There is a dirty trick which involves fiddling with sys.modules.
> For instance:
>
> $ cat x.py
> import sys
>
> class FakeModule(object):

Cute, but it doesn't work in general. Faking a module as a
class fails when you simply call

x()

within the module.

I also tried

modu.__dict__['__setattr__'] = myfun
...
modu.foo = 1 # "myfun" does not get called.

Any more ideas?


John Nagle
From: Stephen Hansen on
On 6/15/10 9:16 PM, John Nagle wrote:
> Cute, but it doesn't work in general. Faking a module as a
> class fails when you simply call
>
> x()
>
> within the module.

Huh? Explain how it doesn't work? I've done it at least twice
(shamefully do I admit this) and it works fine. Real life code.

> Any more ideas?

There aren't any; modules do not follow the class object protocol. They
are simple types with a __dict__ (which you can't change, either, so no
replacing it with a dict that implements __setattr__).

Replacing the module with a class in sys.modules is really the only way
to fake the behavior.

--

Stephen Hansen
... Also: Ixokai
... Mail: me+list/python (AT) ixokai (DOT) io
... Blog: http://meh.ixokai.io/

From: John Nagle on
On 6/15/2010 9:33 PM, Stephen Hansen wrote:
> On 6/15/10 9:16 PM, John Nagle wrote:
>> Cute, but it doesn't work in general. Faking a module as a
>> class fails when you simply call
>>
>> x()
>>
>> within the module.
>
> Huh? Explain how it doesn't work? I've done it at least twice
> (shamefully do I admit this) and it works fine. Real life code.
>
>> Any more ideas?
>
> There aren't any; modules do not follow the class object protocol. They
> are simple types with a __dict__ (which you can't change, either, so no
> replacing it with a dict that implements __setattr__).
>
> Replacing the module with a class in sys.modules is really the only way
> to fake the behavior.

OK, working on this. I can make a module make itself into a
fake class, but can't yet do it to other modules from outside.

John Nagle