[IPython-user] pysh variable substituion and scope
Krishna Mohan Gundu
gkmohan at gmail.com
Sun Jun 4 16:27:43 CDT 2006
Hi Fernando,
> Please always attach patches, never inline them. Python is finicky
> enough about whitespace that it's /very/ easy to end up with a subtly
> broken patch due to indentation issues, after being mangled by the
> mail client's idea of linebreaks. In your case, I couldn't even get
> the patch to apply at all ('malformed patch') by pasting it. It's
> short enough that I just did it by hand, but that's not viable in for
> bigger ones. Some info on the matter:
Sorry for the trouble. I cannot however, for now, provide a diff from
svn as I have other modification I submitted earlier (although
independent).
> The reason why this kind of hack is not a good idea is that it doesn't
> work with more complex cases than your original simple test:
>
>
> longs[~]|2> def foo(x):
> |.> def bar():
> |.> echo "$x"
> |.> bar()
> |.>
> longs[~]|3> foo(3)
>
> Granted, the example above looks a bit contrived, but nested scopes
> are part of the language:
This is a valid example where the code breaks. I expected this and
probably should have waited submitting a patch until I made amends.
> Lexical scoping is a bit tricky to deal with, because most tools (even
> in the language itself, things like eval) can only accept at most a
> globals/locals pair of namespaces for evaluation. But the language
> itself does (as of 2.1) allow for nested scopes.
I am beginning to notice that. It sounds strange to me that the
interface provided to evaluate expressions does not coinicide with the
default interpreters behavior.
> Since you can't know how many frames can be in between the caller and
> the declaration of the variable, a sys._getframe() hack will never do
> this correctly for all cases. One possible solution might be (I'm not
> 100% sure) to properly use, at interpolation time, the func_closure
> generated by the language. This might let you really match the
> language's rules for scoping, explained here:
Unfortunately func_closure has info about only free variables (I still
have to get a hang of what free variables mean)
> Right now I'm not really sure how to do that correctly, and it would
> have to be done (I think) in Itpl's interpolation code. I thought of
> walking the stack (the f_back attributes let you do this easily), but
> you'd need to be sure to stop before hitting ipython's own frames, to
> avoid ipython's internal variables from being interpolated out. It's
> a tricky problem, and given that the language's own machinery already
> does this correctly, I think it's saner to simply let Python deal with
> it.
We cannot do frame backtracking in Itpl since the IPSHELLs execution
stack, so to say, is intervened by call to ipsystem(), which is
executed in a different namespace. Which means Itpl needs to know more
information than it ideally should. I think the right place for it is
ipsystem(). Currently I used a signature to identify the global
namespace of IPSHELL by setting the variable __sig__ in __builtins__.
I used the value 0xa005 because I vaguely remember that's the
signature for boot-sector. One can then backtrack until one exits the
global namespace identified by this signature. In case of embedding
one needs to set/verify signature in appropriate namespace. I dont
know if this solves the problem in general (not likely), since I am
simply merging/overriding the locals from every frame. I will read the
scoping rules of various code blocks and modify it appropriately in
future.
> I'd suggest, if you find that your own code is proving cumbersome to
> write for other reasons, that you try to design a few good utility
> objects that expose the functionality you need in the cleanest
> possible fashion. That will be, in the long term, a far more robust
> and reusable solution than on-the-fly language rewriting by an
> interactive shell.
All I want really is the ability to run shell commands with variable
substituion from anywhere in the python code. I am not thinking big
now.
Example:
==test.ipy==
x = 1
y = 2
z = 3
w = 4
def foo(x):
def bar(y):
def foobar(z):
echo "$x $y $z $w"
foobar(1)
bar(2)
foo(3)
==test.ipy==
prints "3 2 1 4"
I dont have any examples right now with more complex expressions
involving classes, lambdas and the like.
cheers,
Krishna.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: iplib.py.patch
Type: text/x-patch
Size: 2560 bytes
Desc: not available
Url : http://projects.scipy.org/pipermail/ipython-user/attachments/20060604/8bc6b86c/attachment.bin
More information about the IPython-user
mailing list