Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Intercepting binding? (http://www.velocityreviews.com/forums/t699285-intercepting-binding.html)

andrew cooke 09-24-2009 12:15 AM

Intercepting binding?
 

This is a bit vague, I'm afraid, but is there any way for me to take
code like:

a = Foo()
beta = Bar()

and somehow attach the string "a" to the Foo instance and "beta" to
the Bar instance. At some later point in the program I want to be
able to look at the Bar instance and say to the user "this was called
beta in your routine".

The motivation is debugging an embedded domain specific language and
the solution has to be cross platform for Python 3+ (bonus points for
Python 2 too).

Obviously I can parse the code, but I was wondering if there was some
other (no doubt terribly hacky) approach. Even some idea of what to
google for would be a help...

Thanks,
Andrew

andrew cooke 09-24-2009 12:34 AM

Re: Intercepting binding?
 

For example, I assume it's possible to somehow access the dictionary
for the current block, but I can't see how to do this after
assignment. If I do it in the Foo constructor, for example, "a" will
not yet be bound.

On Sep 23, 8:15*pm, andrew cooke <and...@acooke.org> wrote:
> This is a bit vague, I'm afraid, but is there any way for me to take
> code like:
>
> * *a = Foo()
> * *beta = Bar()
>
> and somehow attach the string "a" to the Foo instance and "beta" to
> the Bar instance. *At some later point in the program I want to be

[..]

andrew cooke 09-24-2009 01:10 AM

Re: Intercepting binding?
 
On Sep 23, 8:40*pm, "Rhodri James" <rho...@wildebst.demon.co.uk>
wrote:
> eggs[42] = Foo()
> beans['spam'] = Foo()
> chips.spam = Foo()
> spam[eggs.beans['chips']] = Foo()
> spam.append(Foo())


these are valid points, but in practice the main use (for the
restricted application i care about) is si,ple variables, and this is
an "optional extra" to help the user, so it's OK if it only works
sometimes. at the moment i'd be happy with any half-baked unreliable
solution that is transparent...

andrew

Dave Angel 09-24-2009 02:11 AM

Re: Intercepting binding?
 
andrew cooke wrote:
> This is a bit vague, I'm afraid, but is there any way for me to take
> code like:
>
> a = Foo()
> beta = Bar()
>
> and somehow attach the string "a" to the Foo instance and "beta" to
> the Bar instance. At some later point in the program I want to be
> able to look at the Bar instance and say to the user "this was called
> beta in your routine".
>
> The motivation is debugging an embedded domain specific language and
> the solution has to be cross platform for Python 3+ (bonus points for
> Python 2 too).
>
> Obviously I can parse the code, but I was wondering if there was some
> other (no doubt terribly hacky) approach. Even some idea of what to
> google for would be a help...
>
> Thanks,
> Andrew
>
>

This comes up periodically in this list, and the answer is always
something like: you can't get there from here. As you have noticed, it
can't be done in the __init__() of the object, since the symbol it'll be
bound to doesn't generally exist yet, and even if it does, there's no
way to know which one it is.

You could write a function that the user could voluntarily call at the
end of his function, that would find all symbols of a specified kind,
and store the kind of information you're asking about. But of course,
some class instances should not be added to, and some cannot. So you'd
need some form of filter to indicate which ones to do.

In the sample below, I'll assume you want to do this for all classes
derived from Mybase.

(untested):

def label_stuff(symbols):
for symbol in symbols:
if isinstance(symbols[symbol], Mybase):
symbols[symbol].bind_name = symbol

And the user would simply make a call at the end of each such function,
like:

def my_func():
a = ...
b = ...
label_stuff(locals)



andrew cooke 09-24-2009 02:41 AM

Re: Intercepting binding?
 
On Sep 23, 10:11*pm, Dave Angel <da...@ieee.org> wrote:
> This comes up periodically in this list, and the answer is always
> something like: *you can't get there from here.


Well, I'm both flexible and desperate, so this is a possible route
(perhaps near enough):


import sys

class Foo(object):

def __rlshift__(self, name):
try:
raise Exception()
except:
locals = sys.exc_traceback.tb_frame.f_back.f_locals
locals[name] = self

if __name__ == '__main__':
foo = Foo()
'a' << foo
print(a)


andrew

andrew cooke 09-24-2009 02:57 AM

Re: Intercepting binding?
 

for the record, googling for "f_back.f_locals" reveals a wide variety
of similar hacks and also a cleaner way to access the current frame:
inspect.currentframe()

Steven D'Aprano 09-24-2009 09:20 AM

Re: Intercepting binding?
 
On Wed, 23 Sep 2009 18:10:10 -0700, andrew cooke wrote:

> these are valid points, but in practice the main use (for the restricted
> application i care about) is si,ple variables, and this is an "optional
> extra" to help the user, so it's OK if it only works sometimes. at the
> moment i'd be happy with any half-baked unreliable solution that is
> transparent...


Speaking as a user (although not of Andrew's domain specific language),
I'd like to say to developers PLEASE PLEASE PLEASE don't try to "help me"
with half-baked unreliable solutions that only work sometimes.

There's few things worse than unreliable tools that break just when
you've come to rely on them.




--
Steven

Carl Banks 09-24-2009 11:12 AM

Re: Intercepting binding?
 
On Sep 23, 5:49*pm, "Rhodri James" <rho...@wildebst.demon.co.uk>
wrote:
> On Thu, 24 Sep 2009 01:34:35 +0100, andrew cooke <and...@acooke.org> wrote:
>
> > For example, I assume it's possible to somehow access the dictionary
> > for the current block, but I can't see how to do this after
> > assignment. *If I do it in the Foo constructor, for example, "a" will
> > not yet be bound.

>
> I apologise for failing to notice earlier that you know what you're
> talking about. *I blame the hour :-)
>
> I'm not sure you can access the namespace dictionary of the "current
> block" (module?), that's the problem. *Oh, except via locals(), which
> might do exactly what you're after depending. *Excuse me, I'm being
> very dim tonight.



Hmmm.


@contextlib.contextmanager
def capture_changed_bindings():
before = sys._getframe(2).f_locals.copy()
changed = {}
yield changed
after = sys._getframe(2).f_locals
for key,value in after.iteritems():
if value is changed:
continue
if key not in before or value is not before[key]:
changed[key] = value

def test():
a = 2
b = 3
c = 4
with capture_changed_bindings() as changed:
b = 5
c = 4
d = 6
print changed

test()


Quick and dirty, not robust at all. But you get the idea.

Carl Banks

Carl Banks 09-24-2009 11:33 AM

Re: Intercepting binding?
 
On Sep 23, 7:41*pm, andrew cooke <and...@acooke.org> wrote:
> On Sep 23, 10:11*pm, Dave Angel <da...@ieee.org> wrote:
>
> > This comes up periodically in this list, and the answer is always
> > something like: *you can't get there from here.

>
> Well, I'm both flexible and desperate, so this is a possible route
> (perhaps near enough):
>
> import sys
>
> class Foo(object):
>
> * * def __rlshift__(self, name):
> * * * * try:
> * * * * * * raise Exception()
> * * * * except:
> * * * * * * locals = sys.exc_traceback.tb_frame.f_back.f_locals
> * * * * * * locals[name] = self
>
> if __name__ == '__main__':
> * * foo = Foo()
> * * 'a' << foo
> * * print(a)


Did you try this inside a function? (Hint: it won't work in a
function.)

BTW, if you are desperate to do this then I'd say you lack good
perspective. You are subverting some of the most basic behavior of
Python here for something of marginal and only occasional usefulness.
If you are that desperate just retype the name, it won't be the end of
the world.

a = Foo('a')


Carl Banks

andrew cooke 09-24-2009 11:49 AM

Re: Intercepting binding?
 
On Sep 24, 7:12*am, Carl Banks <pavlovevide...@gmail.com> wrote:
> * * with capture_changed_bindings() as changed:
> * * * * b = 5
> * * * * c = 4
> * * * * d = 6
> * * print changed
>
> test()
>
> Quick and dirty, not robust at all. *But you get the idea.
>
> Carl Banks


brilliant. using the with context is an excellent idea. thanks very
much.

andrew


All times are GMT. The time now is 12:39 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.