Intercepting binding?

Discussion in 'Python' started by andrew cooke, Sep 24, 2009.

  1. andrew cooke

    andrew cooke Guest

    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, Sep 24, 2009
    #1
    1. Advertising

  2. andrew cooke

    andrew cooke Guest

    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 <> 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, Sep 24, 2009
    #2
    1. Advertising

  3. andrew cooke

    andrew cooke Guest

    On Sep 23, 8:40 pm, "Rhodri James" <>
    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
    andrew cooke, Sep 24, 2009
    #3
  4. andrew cooke

    Dave Angel Guest

    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)
    Dave Angel, Sep 24, 2009
    #4
  5. andrew cooke

    andrew cooke Guest

    On Sep 23, 10:11 pm, Dave Angel <> 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, Sep 24, 2009
    #5
  6. andrew cooke

    andrew cooke Guest

    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()
    andrew cooke, Sep 24, 2009
    #6
  7. 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
    Steven D'Aprano, Sep 24, 2009
    #7
  8. andrew cooke

    Carl Banks Guest

    On Sep 23, 5:49 pm, "Rhodri James" <>
    wrote:
    > On Thu, 24 Sep 2009 01:34:35 +0100, andrew cooke <> 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, Sep 24, 2009
    #8
  9. andrew cooke

    Carl Banks Guest

    On Sep 23, 7:41 pm, andrew cooke <> wrote:
    > On Sep 23, 10:11 pm, Dave Angel <> 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
    Carl Banks, Sep 24, 2009
    #9
  10. andrew cooke

    andrew cooke Guest

    On Sep 24, 7:12 am, Carl Banks <> 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
    andrew cooke, Sep 24, 2009
    #10
  11. andrew cooke

    andrew cooke Guest

    On Sep 24, 5:20 am, Steven D'Aprano
    <> wrote:
    > 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.


    The context is that I am looking at how best to provide debugging
    support for a recursive descent parser. If the actions are pure then
    the whole thing is deterministic, so it might be possible to do
    something like "buddha" (a declarative debugger for haskell). I'm
    also looking for a paper that was linked to somewhere this last month
    or so on one of the popular sites/blogs about debugging prolog (since
    the two are closely related - depth first search etc) - I know this is
    vague, but if it rings a bell with anyone... Anyway, doing this in
    pure Python makes risks losing the information associated with
    variable names. I was wondering how I might reduce that.

    The reason I asked for "unreliable half-baked" solutions is that I am
    exploring what might be possible and, in my experience, this group
    prefers to lecture me on what they think I should do rather than
    answer the damn question. I was hoping that by explicitly saying that
    reliability is not important, people might feel more free to give
    "wild" ideas that I could learn from and improve on.

    It's significant, depressing, and not at all surprising that every
    person who replied to this thread told me, in one way or another, that
    was I was asking was wrong or impossible or foolhardy.

    If I want your advice on how to write popular tools, you can be sure I
    will come and ask you for it. That is not what I asked for here.

    But since we're all passing round unsolicited advice, here's some from
    me.

    Being an anal retentive will get you a long way in programming.
    Dotting the "i"s and crossing the "t"s is 99% of what it's all about.
    I agree. But the last 1% requires a little bit of imagination. You
    should try it one day.

    Andrew
    andrew cooke, Sep 24, 2009
    #11
  12. andrew cooke

    Carl Banks Guest

    On Sep 24, 5:39 am, andrew cooke <> wrote:
    > It's significant, depressing, and not at all surprising that every
    > person who replied to this thread told me, in one way or another, that
    > was I was asking was wrong or impossible or foolhardy.


    People on this list are volunteers, who have no obligation to help.

    If you want always friendly, enabling advice I'm sure there are good
    support services out there who would be happy not to second-guess you
    for a fee.

    Otherwise, grow thicker skin.


    Carl Banks
    Carl Banks, Sep 25, 2009
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timothy Parez
    Replies:
    0
    Views:
    378
    Timothy Parez
    Mar 6, 2004
  2. Al
    Replies:
    1
    Views:
    392
    RickB
    Jul 1, 2003
  3. Nick
    Replies:
    2
    Views:
    342
  4. Stu
    Replies:
    1
    Views:
    348
    William F. Robertson, Jr.
    Feb 22, 2005
  5. Philip

    Data Binding Exceptions - Intercepting

    Philip, Oct 27, 2008, in forum: ASP .Net Web Controls
    Replies:
    1
    Views:
    129
    Philip
    Oct 27, 2008
Loading...

Share This Page