github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/tools/grumprun (about) 1 #!/usr/bin/env python 2 3 # Copyright 2016 Google Inc. All Rights Reserved. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """grumprun compiles and runs a snippet of Python using Grumpy. 18 19 Usage: $ grumprun -m <module> # Run the named module. 20 $ echo 'print "hola!"' | grumprun # Execute Python code from stdin. 21 """ 22 23 import argparse 24 import os 25 import random 26 import shutil 27 import string 28 import subprocess 29 import sys 30 import tempfile 31 32 from grumpy.compiler import imputil 33 34 35 parser = argparse.ArgumentParser() 36 parser.add_argument('-m', '--modname', help='Run the named module') 37 38 module_tmpl = string.Template("""\ 39 package main 40 import ( 41 \t"os" 42 \t"grumpy" 43 \tmod "$package" 44 $imports 45 ) 46 func main() { 47 \tgrumpy.ImportModule(grumpy.NewRootFrame(), "traceback") 48 \tos.Exit(grumpy.RunMain(mod.Code)) 49 } 50 """) 51 52 53 def main(args): 54 gopath = os.getenv('GOPATH', None) 55 if not gopath: 56 print >> sys.stderr, 'GOPATH not set' 57 return 1 58 59 modname = args.modname 60 workdir = tempfile.mkdtemp() 61 try: 62 if modname: 63 # Find the script associated with the given module. 64 for d in gopath.split(os.pathsep): 65 script = imputil.find_script( 66 os.path.join(d, 'src', '__python__'), modname) 67 if script: 68 break 69 else: 70 print >> sys.stderr, "can't find module", modname 71 return 1 72 else: 73 # Generate a dummy python script on the GOPATH. 74 modname = ''.join(random.choice(string.ascii_letters) for _ in range(16)) 75 py_dir = os.path.join(workdir, 'src', '__python__') 76 mod_dir = os.path.join(py_dir, modname) 77 os.makedirs(mod_dir) 78 script = os.path.join(py_dir, 'module.py') 79 with open(script, 'w') as f: 80 f.write(sys.stdin.read()) 81 gopath = gopath + os.pathsep + workdir 82 os.putenv('GOPATH', gopath) 83 # Compile the dummy script to Go using grumpc. 84 fd = os.open(os.path.join(mod_dir, 'module.go'), os.O_WRONLY | os.O_CREAT) 85 try: 86 p = subprocess.Popen('grumpc ' + script, stdout=fd, shell=True) 87 if p.wait(): 88 return 1 89 finally: 90 os.close(fd) 91 92 names = imputil.calculate_transitive_deps(modname, script, gopath) 93 # Make sure traceback is available in all Python binaries. 94 names.add('traceback') 95 go_main = os.path.join(workdir, 'main.go') 96 package = _package_name(modname) 97 imports = ''.join('\t_ "' + _package_name(name) + '"\n' for name in names) 98 with open(go_main, 'w') as f: 99 f.write(module_tmpl.substitute(package=package, imports=imports)) 100 return subprocess.Popen('go run ' + go_main, shell=True).wait() 101 finally: 102 shutil.rmtree(workdir) 103 104 105 def _package_name(modname): 106 if modname.startswith('__go__/'): 107 return '__python__/' + modname 108 return '__python__/' + modname.replace('.', '/') 109 110 111 if __name__ == '__main__': 112 sys.exit(main(parser.parse_args()))