def testOilFlags(self): s = args.OilFlags() s.Flag('-docstring', args.Bool, default=True) s.Flag('-out-file', args.Str) s.Flag('-retries', args.Int) arg, i = s.ParseArgv(['-docstring=0', 'x', 'y']) self.assertEqual(False, arg.docstring) self.assertEqual(None, arg.out_file) self.assertEqual(1, i) # This turns it on too arg, i = s.ParseArgv(['-docstring', '0', 'x', 'y']) self.assertEqual(True, arg.docstring) self.assertEqual(None, arg.out_file) self.assertEqual(1, i) arg, i = s.ParseArgv(['-out-file', 'out', 'y']) self.assertEqual(True, arg.docstring) self.assertEqual('out', arg.out_file) self.assertEqual(2, i) arg, i = s.ParseArgv(['-retries', '3']) self.assertEqual(3, arg.retries) arg, i = s.ParseArgv(['-retries=3']) self.assertEqual(3, arg.retries) # Like GNU: anything that starts with -- is parsed like an option. self.assertRaises(args.UsageError, s.ParseArgv, ['---']) self.assertRaises(args.UsageError, s.ParseArgv, ['-oops']) # Invalid boolean arg self.assertRaises(args.UsageError, s.ParseArgv, ['--docstring=YEAH']) arg, i = s.ParseArgv(['--']) self.assertEqual(1, i) arg, i = s.ParseArgv(['-']) self.assertEqual(0, i) arg, i = s.ParseArgv(['abc']) self.assertEqual(0, i)
# / pattern file* / arg 1 pattern "Regular expression" arg 2- file "Regular expression" } var opt = grep_opts.Parse(ARGV) opt.invert opt.after opt.pattern opt.file """ def __call__(self, cmd_val): raise NotImplementedError JSON_WRITE_SPEC = args.OilFlags() JSON_WRITE_SPEC.Flag('-pretty', args.Bool, default=True, help='Whitespace in output (default true)') JSON_WRITE_SPEC.Flag('-indent', args.Int, default=2, help='Indent JSON by this amount') JSON_READ_SPEC = args.OilFlags() # yajl has this option JSON_READ_SPEC.Flag('-validate', args.Bool, default=True, help='Validate UTF-8')
def OpyCommandMain(argv): """Dispatch to the right action.""" # TODO: Use core/args. #opts, argv = Options().parse_args(argv) try: action = argv[0] except IndexError: raise args.UsageError('opy: Missing required subcommand.') argv = argv[1:] # TODO: Should I do input.ReadRequiredArg()? # That will shift the input. if action in ( 'parse', 'parse-with', 'compile', 'dis', 'ast', 'symbols', 'cfg', 'compile-ovm', 'eval', 'repl', 'run', 'run-ovm'): loader = pyutil.GetResourceLoader() f = loader.open(GRAMMAR_REL_PATH) contents = f.read() f.close() gr = grammar.Grammar() gr.loads(contents) # In Python 2 code, always use from __future__ import print_function. try: del gr.keywords["print"] except KeyError: pass symbols = Symbols(gr) pytree.Init(symbols) # for type_repr() pretty printing transformer.Init(symbols) # for _names and other dicts compiler = skeleton.Compiler(gr) else: # e.g. pgen2 doesn't use any of these. Maybe we should make a different # tool. compiler = None # TODO: Also have a run_spec for 'opyc run'. compile_spec = args.OilFlags() compile_spec.Flag('-emit-docstring', args.Bool, default=True, help='Whether to emit docstrings') compile_spec.Flag('-fast-ops', args.Bool, default=True, help='Whether to emit LOAD_FAST, STORE_FAST, etc.') compile_spec.Flag('-oil-subset', args.Bool, default=False, help='Only allow the constructs necessary to implement' 'Oil. Example: using multiple inheritance will abort ' 'compilation.') # # Actions # if action == 'pgen2': grammar_path = argv[0] marshal_path = argv[1] WriteGrammar(grammar_path, marshal_path) elif action == 'stdlib-parse': # This is what the compiler/ package was written against. import parser py_path = argv[1] with open(py_path) as f: st = parser.suite(f.read()) tree = st.totuple() printer = TupleTreePrinter(HostStdlibNames()) printer.Print(tree) n = CountTupleTree(tree) log('COUNT %d', n) elif action == 'lex': py_path = argv[0] with open(py_path) as f: tokens = tokenize.generate_tokens(f.readline) for typ, val, start, end, unused_line in tokens: print('%10s %10s %-10s %r' % (start, end, token.tok_name[typ], val)) elif action == 'lex-names': # Print all the NAME tokens. for py_path in argv: log('Lexing %s', py_path) with open(py_path) as f: tokens = tokenize.generate_tokens(f.readline) for typ, val, start, end, unused_line in tokens: if typ == token.NAME: print(val) elif action == 'parse': py_path = argv[0] with open(py_path) as f: tokens = tokenize.generate_tokens(f.readline) p = parse.Parser(gr) pnode = driver.PushTokens(p, tokens, gr, 'file_input') printer = ParseTreePrinter(transformer._names) # print raw nodes printer.Print(pnode) # Parse with an arbitrary grammar, but the Python lexer. elif action == 'parse-with': grammar_path = argv[0] start_symbol = argv[1] code_str = argv[2] with open(grammar_path) as f: gr = pgen.MakeGrammar(f) f = cStringIO.StringIO(code_str) tokens = tokenize.generate_tokens(f.readline) p = parse.Parser(gr) # no convert= try: pnode = driver.PushTokens(p, tokens, gr, start_symbol) except parse.ParseError as e: # Extract location information and show it. _, _, (lineno, offset) = e.opaque # extra line needed for '\n' ? lines = code_str.splitlines() + [''] line = lines[lineno-1] log(' %s', line) log(' %s^', ' '*offset) log('Parse Error: %s', e) return 1 printer = ParseTreePrinter(transformer._names) # print raw nodes printer.Print(pnode) elif action == 'ast': # output AST opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] with open(py_path) as f: graph = compiler.Compile(f, opt, 'exec', print_action='ast') elif action == 'symbols': # output symbols opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] with open(py_path) as f: graph = compiler.Compile(f, opt, 'exec', print_action='symbols') elif action == 'cfg': # output Control Flow Graph opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] with open(py_path) as f: graph = compiler.Compile(f, opt, 'exec', print_action='cfg') elif action == 'compile': # 'opyc compile' is pgen2 + compiler2 # spec.Arg('action', ['foo', 'bar']) # But that leads to some duplication. opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] out_path = argv[i+1] with open(py_path) as f: co = compiler.Compile(f, opt, 'exec') log("Compiled to %d bytes of top-level bytecode", len(co.co_code)) # Write the .pyc file with open(out_path, 'wb') as out_f: h = misc.getPycHeader(py_path) out_f.write(h) marshal.dump(co, out_f) elif action == 'compile-ovm': # NOTE: obsolete from ovm2 import oheap2 opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] out_path = argv[i+1] # Compile to Python bytecode (TODO: remove ovm_codegen.py) mode = 'exec' with open(py_path) as f: co = compiler.Compile(f, opt, mode) if 1: with open(out_path, 'wb') as out_f: oheap2.Write(co, out_f) return 0 log("Compiled to %d bytes of top-level bytecode", len(co.co_code)) # Write the .pyc file with open(out_path, 'wb') as out_f: if 1: out_f.write(co.co_code) else: h = misc.getPycHeader(py_path) out_f.write(h) marshal.dump(co, out_f) log('Wrote only the bytecode to %r', out_path) elif action == 'eval': # Like compile, but parses to a code object and prints it opt, i = compile_spec.ParseArgv(argv) py_expr = argv[i] f = skeleton.StringInput(py_expr, '<eval input>') co = compiler.Compile(f, opt, 'eval') v = dis_tool.Visitor() v.show_code(co) print() print('RESULT:') print(eval(co)) elif action == 'repl': # Like eval in a loop while True: py_expr = raw_input('opy> ') f = skeleton.StringInput(py_expr, '<REPL input>') # TODO: change this to 'single input'? Why doesn't this work? co = compiler.Compile(f, opt, 'eval') v = dis_tool.Visitor() v.show_code(co) print(eval(co)) elif action == 'dis-tables': out_dir = argv[0] pyc_paths = argv[1:] out = TableOutput(out_dir) for pyc_path in pyc_paths: with open(pyc_path) as f: magic, unixtime, timestamp, code = dis_tool.unpack_pyc(f) WriteDisTables(pyc_path, code, out) out.Close() elif action == 'dis': opt, i = compile_spec.ParseArgv(argv) path = argv[i] v = dis_tool.Visitor() if path.endswith('.py'): with open(path) as f: co = compiler.Compile(f, opt, 'exec') log("Compiled to %d bytes of top-level bytecode", len(co.co_code)) v.show_code(co) else: # assume pyc_path with open(path, 'rb') as f: v.Visit(f) elif action == 'dis-md5': pyc_paths = argv if not pyc_paths: raise args.UsageError('dis-md5: At least one .pyc path is required.') for path in pyc_paths: h = hashlib.md5() with open(path) as f: magic = f.read(4) h.update(magic) ignored_timestamp = f.read(4) while True: b = f.read(64 * 1024) if not b: break h.update(b) print('%6d %s %s' % (os.path.getsize(path), h.hexdigest(), path)) elif action == 'run': # Compile and run, without writing pyc file # TODO: Add an option like -v in __main__ #level = logging.DEBUG if args.verbose else logging.WARNING #logging.basicConfig(level=level) #logging.basicConfig(level=logging.DEBUG) opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] opy_argv = argv[i:] if py_path.endswith('.py'): with open(py_path) as f: co = compiler.Compile(f, opt, 'exec') num_ticks = execfile.run_code_object(co, opy_argv) elif py_path.endswith('.pyc') or py_path.endswith('.opyc'): with open(py_path) as f: f.seek(8) # past header. TODO: validate it! co = marshal.load(f) num_ticks = execfile.run_code_object(co, opy_argv) else: raise args.UsageError('Invalid path %r' % py_path) elif action == 'run-ovm': # Compile and run, without writing pyc file opt, i = compile_spec.ParseArgv(argv) py_path = argv[i] opy_argv = argv[i+1:] if py_path.endswith('.py'): #mode = 'exec' mode = 'ovm' # OVM bytecode is different! with open(py_path) as f: co = compiler.Compile(f, opt, mode) log('Compiled to %d bytes of OVM code', len(co.co_code)) num_ticks = ovm.run_code_object(co, opy_argv) elif py_path.endswith('.pyc') or py_path.endswith('.opyc'): with open(py_path) as f: f.seek(8) # past header. TODO: validate it! co = marshal.load(f) num_ticks = ovm.run_code_object(co, opy_argv) else: raise args.UsageError('Invalid path %r' % py_path) else: raise args.UsageError('Invalid action %r' % action)
state.SetStringDynamic(self.mem, 'OPTIND', str(optind)) if match.IsValidVarName(var_name): state.SetStringDynamic(self.mem, var_name, opt_char) else: # NOTE: The builtin has PARTIALLY filed. This happens in all shells # except mksh. raise args.UsageError('got invalid variable name %r' % var_name, span_id=var_spid) return status ECHO_SPEC = _Register('echo') ECHO_SPEC.ShortFlag('-e') # no backslash escapes ECHO_SPEC.ShortFlag('-n') OIL_ECHO_SPEC = args.OilFlags() OIL_ECHO_SPEC.Flag('-sep', args.Str, default='\n', help='Characters to separate each argument') OIL_ECHO_SPEC.Flag('-end', args.Str, default='\n', help='Characters to terminate the whole invocation') OIL_ECHO_SPEC.Flag('-n', args.Bool, default=False, help="Omit newline (synonym for -end '')") class Echo(object):