with ssh() pt1: Capturing the body of a with statement
I've been advancing a lot with ayrton
.
A lot of things already work and I'm still toying with the final syntax, but
this is not what I came to talk about.
Since its inception, I had one particular idea for a scripting language: the
ability to connect through ssh
to another machine and execute some code there,
without a requirement that the code must be already a script in the remote
machine, and that has sane ways to reference variables both local to the instance
of the code running in the remote machine and variables local to the 'parent'
script. This is more or less what I'm talking about:
ssh $user_machine '\ cd /foo; \ cd $(find . -type d -name "Fo-Obarbaz-*" | sort -u | tail -1); \ file=$(ls -1 *_LOG); \ echo "File: $file"; \ cat $file' > local_file
This example is simple in the sense that it only references variable local to the remote execution; just try to imagine how much escaping you would need for referencing both types of variables.
Python3
has a very handy construct for this: context managers. Imagine that
you could write:
with ssh (user_machine, _out=open (local_file, 'w+')): cd ('/foo') cd (tail (sort (find ('. -type d -name Fo-Obarbaz-*'), '-u') '-1')) file= ls ('-l', bash ('*_LOG')) print ("File: %s" % file) cat (file)
That's my current goal. So I set off to find how to achieve this. The first part
of the journey is to find the body of the with
statement. Suppose this simpler
code:
# file with_ssh.ay with ssh ('localhost'): print ('yes!')
Enter the ast
module:
import ast t= ast.parse (open ('with_ssh.ay').read ()) for node in ast.walk (t): if type (node)==ast.With and node.items[0].context_expr.func.id=='ssh': code= node.body f= ast.Module(body=code) f_c= compile (f, 'foo', 'exec') exec (f_c)
This small piece of code prints yes!
without a hitch. My work is done here...
... except that I still have to find how to send the code via ssh
1, most probably
with all its dependencies, probably check that the python version matches, compile
it and execute it there. And chose a way to reference variables in the calling
environment and/or transmit them. But that's for another post :)
This kind of AST manipulation could also allow me to properly implement |
.
-
Guess what:
ast.AST
's arepickle
'able :) ↩