Skip to content

Commit a81339b

Browse files
committed
Rework how arguments are parsed, hopefully fixing issue bpython#101.
Instead of detecting invalid arguments up front for falling back to python we now let optparse parse and catch an exception if it fails. Instead of splitting the list into "our" arguments and the ones for the script we run we use the optparse allow_interspersed_args option.
1 parent 15e7c20 commit a81339b

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

bpython/args.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
from bpython import __version__
1313
from bpython.config import loadini, Struct, migrate_rc
1414

15+
16+
class OptionParserFailed(ValueError):
17+
"""Raised by the RaisingOptionParser for a bogus commandline."""
18+
19+
20+
class RaisingOptionParser(OptionParser):
21+
def error(self, msg):
22+
raise OptionParserFailed()
23+
24+
1525
def parse(args, extras=None):
1626
"""Receive an argument list - if None, use sys.argv - parse all args and
1727
take appropriate action. Also receive optional extra options: this should
@@ -39,10 +49,16 @@ def parse(args, extras=None):
3949
if args is None:
4050
args = sys.argv[1:]
4151

42-
parser = OptionParser(usage='Usage: %prog [options] [file [args]]\n'
43-
'NOTE: If bpython sees an argument it does '
44-
'not know, execution falls back to the '
45-
'regular Python interpreter.')
52+
parser = RaisingOptionParser(
53+
usage='Usage: %prog [options] [file [args]]\n'
54+
'NOTE: If bpython sees an argument it does '
55+
'not know, execution falls back to the '
56+
'regular Python interpreter.')
57+
# This is not sufficient if bpython gains its own -m support
58+
# (instead of falling back to Python itself for that).
59+
# That's probably fixable though, for example by having that
60+
# option swallow all remaining arguments in a callback.
61+
parser.disable_interspersed_args()
4662
parser.add_option('--config', '-c', default='~/.bpython/config',
4763
help='use CONFIG instead of default config file')
4864
parser.add_option('--interactive', '-i', action='store_true',
@@ -59,17 +75,11 @@ def parse(args, extras=None):
5975
extras_group.add_option(option)
6076
parser.add_option_group(extras_group)
6177

62-
all_args = set(parser._short_opt.keys() + parser._long_opt.keys())
63-
if args and not all_args.intersection(arg.split('=')[0] for arg in args):
78+
try:
79+
options, args = parser.parse_args(args)
80+
except OptionParserFailed:
6481
# Just let Python handle this
6582
os.execv(sys.executable, [sys.executable] + args)
66-
else:
67-
# Split args in bpython args and args for the executed file
68-
real_args = list(takewhile(lambda arg: arg.split('=')[0] in all_args,
69-
args))
70-
exec_args = args[len(real_args):]
71-
72-
options, args = parser.parse_args(real_args)
7383

7484
if options.version:
7585
print 'bpython version', __version__,
@@ -91,7 +101,7 @@ def parse(args, extras=None):
91101

92102
loadini(config, options.config)
93103

94-
return config, options, exec_args
104+
return config, options, args
95105

96106
def exec_code(interpreter, args):
97107
"""

0 commit comments

Comments
 (0)