What *instance* called me & proxy methods

Ken Seehof kens at sightreader.com
Wed Mar 28 13:07:35 EST 2001


You want 'im_self'.

Also, you might find 'im_func' handy as well.  It returns the
function, so you can unbind a bound method.

>>> class X:
...  def a(self):
...   return 1
...
>>> x = X()
>>> x.a
<method X.a of X instance at 01390DFC>
>>> x.a.im_self
<__main__.X instance at 01390DFC>
>>> x.a.im_func
<function a at 0139105C>

- Ken Seehof

----- Original Message -----
From: "Carlos Alberto Reis Ribeiro" <cribeiro at mail.inet.com.br>
To: <python-list at python.org>
Sent: Wednesday, March 28, 2001 8:57 AM
Subject: What *instance* called me & proxy methods


> I've seen some talk on how to get the name of the caller. I got a related
> problem to solve, only slightly more complicated.
>
> Can I know what *instance* called a method? I'm not talking about "self"
> here, because we *can* call a method using other techniques, such as
> copying the instance method pointer directly:
>
>     >>> class myclass:
>     ...   def hello(self):
>     ...     print "hi! I'm ", self
>     >>> class myproxy:
>     ...   pass
>     >>> a = myclass()
>     >>> a.hello()
>     hi! I'm  <__main__.myclass instance at 015093EC>
>     >>> m = a.hello
>     >>> p = myproxy()
>     >>> p.m = m
>     >>> p.m()
>     hi! I'm  <__main__.myclass instance at 015093EC>
>
> In both cases, hello() received the same value as the self parameter. This
> is exactly what I need; in fact, the im_self attribute of the instance
> method stores the pointer to self, which explains this behavior. However,
I
> would also like to have some information to differentiate between these
two
> calls. My goal is to implement some security checking as part of my
> proxy/adapter module [1]. I have already tried some simple minded
> approaches (too many to list here), so far with no success.
>
> The best solution the I have thought so far can be implemented as a Python
> extension - if I manage to put my Linux box up and running (I'm gcc-less
> right now :-).
>
> 1) Implement a new object called 'ProxyMethod', derived of 'instance
>     method', with the following differences:
>
>     * It does not make the im_* attributes visible to the outside
>       world;
>
>     * It stores a read-only attribute to the proxy that 'owns' the
>       ProxyMethod.
>
> 2) The 'ProxyMethod' constructor would take a instance method and
>     build the proxy method from it.
>
> 3) The information about the proxy would need to be stored somewhere
>     in the call stack. I dont know if it is possible without changing
>     some of the Python internals.
>
> 4) The runtime semantics of the 'ProxyMethod' would be about the
>     same as the ones of the instance method - just a direct call,
>     without any extra intermediation.
>
> I would like to know what the community thinks about turning this into a
> PEP. Maybe we can find a simpler solution, or it's better to keep this as
a
> module outside the distribution.
>
> For now I have a very simple Python implementation. It's far from perfect,
> and it has some undesirable side effects because it is not completely
> transparent, and it needs some intermediate processing. The only way that
I
> found to signal to the proxied object about the existence of the proxy was
> to create a temporary "proxy" attribute (see point (3) above). However, it
> serves it purpose as a proof-of-concept:
>
> ----------------------------------------------------------------------
> TEST RESULT
>
>  >>> n = NuclearArsenal()
>  >>> n.NuclearAttack("NY")
> Only the proxy can order the attack
>  >>> p = Proxy()
>  >>> p.attack = ProxyMethod(n.NuclearAttack, p)
>  >>> p.attack("NY")
> Boooom! NY destroyed
>
> ----------------------------------------------------------------------
> CODE
>
> """ ProxyMethod proof-of-concept
>      (c) 2001 Carlos Ribeiro - cribeiro at mail.inet.com.br
>      Released in public domain for use "as-is"
> """
>
> from types import *
>
> class Proxy:
>    pass
>
> class ProxyMethod:
>
>    def __init__(self, im, p):
>      if type(im) != MethodType:
>        raise "A proxy needs a method"
>      if p.__class__ != Proxy:
>        raise "A proxy method is bounded to a proxy"
>      self.im = im
>      self.p  = p
>
>    def __call__(self, *a):
>      # set a flag inside the target instance
>      setattr(self.im.im_self, 'proxy', self.p)
>      # do the call
>      self.im(*a)
>      # clear the flag
>      delattr(self.im.im_self, 'proxy')
>
> class NuclearArsenal:
>    def NuclearAttack(self, city):
>      if getattr(self, 'proxy', None):
>        # called through the proxy
>        print "Boooom! %s destroyed" % (city)
>      else:
>        print "Only the proxy can order the attack"
>
> ----------------------------------------------------------------------
>
> Carlos Ribeiro
>
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list






More information about the Python-list mailing list