|
| 1 | +""" |
| 2 | +Module to handle command line argument parsing, for all front-ends. |
| 3 | +""" |
| 4 | + |
| 5 | +import os |
| 6 | +import sys |
| 7 | +import code |
| 8 | +from optparse import OptionParser, OptionGroup |
| 9 | +from itertools import takewhile |
| 10 | + |
| 11 | +from bpython import __version__ |
| 12 | +from bpython.config import loadini, Struct, migrate_rc |
| 13 | + |
| 14 | +def parse(args, extras=None): |
| 15 | + """Receive an argument list - if None, use sys.argv - parse all args and |
| 16 | + take appropriate action. Also receive optional extra options: this should |
| 17 | + be a tuple of (title, description, options) |
| 18 | + title: The title for the option group |
| 19 | + description: A full description of the option group |
| 20 | + options: A list of optparse.Option objects to be added to the |
| 21 | + group |
| 22 | +
|
| 23 | + e.g.: |
| 24 | +
|
| 25 | + parse(['-i', '-m', 'foo.py'], |
| 26 | + ('Front end-specific options', |
| 27 | + 'A full description of what these options are for', |
| 28 | + [optparse.Option('-f', action='store_true', dest='f', help='Explode'), |
| 29 | + optparse.Option('-l', action='store_true', dest='l', help='Love')])) |
| 30 | + |
| 31 | +
|
| 32 | + Return a tuple of (config, options, exec_args) wherein "config" is the |
| 33 | + config object either parsed from a default/specified config file or default |
| 34 | + config options, "options" is the parsed options from |
| 35 | + OptionParser.parse_args, and "exec_args" are the args (if any) to be parsed |
| 36 | + to the executed file (if any). |
| 37 | + """ |
| 38 | + if args is None: |
| 39 | + args = sys.argv[1:] |
| 40 | + |
| 41 | + parser = OptionParser(usage='Usage: %prog [options] [file [args]]\n' |
| 42 | + 'NOTE: If bpython sees an argument it does ' |
| 43 | + 'not know, execution falls back to the ' |
| 44 | + 'regular Python interpreter.') |
| 45 | + parser.add_option('--config', '-c', default='~/.bpython/config', |
| 46 | + help='use CONFIG instead of default config file') |
| 47 | + parser.add_option('--interactive', '-i', action='store_true', |
| 48 | + help='Drop to bpython shell after running file ' |
| 49 | + 'instead of exiting') |
| 50 | + parser.add_option('--quiet', '-q', action='store_true', |
| 51 | + help="Don't flush the output to stdout.") |
| 52 | + parser.add_option('--version', '-V', action='store_true', |
| 53 | + help='print version and exit') |
| 54 | + |
| 55 | + if extras is not None: |
| 56 | + extras_group = OptionGroup(parser, extras[0], extras[1]) |
| 57 | + for option in extras[2]: |
| 58 | + extras_group.option_list.append(option) |
| 59 | + parser.add_option_group(extras_group) |
| 60 | + |
| 61 | + all_args = set(parser._short_opt.keys() + parser._long_opt.keys()) |
| 62 | + if args and not all_args.intersection(args): |
| 63 | + # Just let Python handle this |
| 64 | + os.execv(sys.executable, [sys.executable] + args) |
| 65 | + else: |
| 66 | + # Split args in bpython args and args for the executed file |
| 67 | + real_args = list(takewhile(lambda arg: arg in all_args, args)) |
| 68 | + exec_args = args[len(real_args):] |
| 69 | + |
| 70 | + options, args = parser.parse_args(real_args) |
| 71 | + |
| 72 | + if options.version: |
| 73 | + print 'bpython version', __version__, |
| 74 | + print 'on top of Python', sys.version.split()[0] |
| 75 | + print '(C) 2008-2009 Bob Farrell et al. See AUTHORS for detail.' |
| 76 | + raise SystemExit |
| 77 | + |
| 78 | + if not (sys.stdin.isatty() and sys.stdout.isatty()): |
| 79 | + interpreter = code.InteractiveInterpreter() |
| 80 | + interpreter.runsource(sys.stdin.read()) |
| 81 | + raise SystemExit |
| 82 | + |
| 83 | + path = os.path.expanduser('~/.bpythonrc') |
| 84 | + # migrating old configuration file |
| 85 | + if os.path.isfile(path): |
| 86 | + migrate_rc(path) |
| 87 | + config = Struct() |
| 88 | + |
| 89 | + loadini(config, options.config) |
| 90 | + |
| 91 | + return config, options, exec_args |
| 92 | + |
| 93 | +def exec_code(interpreter, args): |
| 94 | + """ |
| 95 | + Helper to execute code in a given interpreter. args should be a [faked] |
| 96 | + sys.argv |
| 97 | + """ |
| 98 | + with open(args[0], 'r') as sourcefile: |
| 99 | + code_obj = compile(sourcefile.read(), args[0], 'exec') |
| 100 | + old_argv, sys.argv = sys.argv, args |
| 101 | + interpreter.runcode(code_obj) |
| 102 | + sys.argv = old_argv |
0 commit comments