Skip to content

Commit 13f97be

Browse files
committed
Allow execution of Python files passed on command line.
This mimics CPython's behaviour and makes it possible to use bpython as an alternative to the python command (although bpython still requires a Python interpreter of course).
1 parent 1485b10 commit 13f97be

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

bpython/cli.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import unicodedata
4848
import textwrap
4949
from cStringIO import StringIO
50+
from itertools import takewhile
5051
from locale import LC_ALL, getpreferredencoding, setlocale
5152
from optparse import OptionParser
5253
from urlparse import urljoin
@@ -1939,7 +1940,7 @@ def newwin(*args):
19391940
return win
19401941

19411942

1942-
def main_curses(scr):
1943+
def main_curses(scr, args, interactive=True):
19431944
"""main function for the curses convenience wrapper
19441945
19451946
Initialise the two main objects: the interpreter
@@ -1984,6 +1985,14 @@ def main_curses(scr):
19841985
sys.stdout = repl
19851986
sys.stderr = repl
19861987

1988+
if args:
1989+
with open(args[0], 'r') as sourcefile:
1990+
code_obj = compile(sourcefile.read(), args[0], 'exec')
1991+
old_argv, sys.argv = sys.argv, args
1992+
interpreter.runcode(code_obj)
1993+
sys.argv = old_argv
1994+
if not interactive:
1995+
return repl.getstdout()
19871996

19881997
repl.repl()
19891998
if OPTS.hist_length:
@@ -1997,15 +2006,30 @@ def main_curses(scr):
19972006

19982007
def main(args=None):
19992008
if args is None:
2000-
args = sys.argv
2009+
args = sys.argv[1:]
20012010

2002-
parser = OptionParser()
2011+
parser = OptionParser(usage='Usage: %prog [options] [file [args]]\n'
2012+
'NOTE: If bpython sees an argument it does '
2013+
'not know, execution falls back to the '
2014+
'regular Python interpreter.')
20032015
parser.add_option('--config', '-c', default='~/.bpython.ini',
20042016
help='use CONFIG instead of default config file')
2017+
parser.add_option('--interactive', '-i', action='store_true',
2018+
help='Drop to bpython shell after running file '
2019+
'instead of exiting')
20052020
parser.add_option('--version', '-V', action='store_true',
20062021
help='print version and exit')
20072022

2008-
options, args = parser.parse_args(args)
2023+
all_args = set(parser._short_opt.keys() + parser._long_opt.keys())
2024+
if args and not all_args.intersection(args):
2025+
# Just let Python handle this
2026+
os.execv(sys.executable, [sys.executable] + args)
2027+
else:
2028+
# Split args in bpython args and args for the executed file
2029+
real_args = list(takewhile(lambda arg: arg in all_args, args))
2030+
exec_args = args[len(real_args):]
2031+
2032+
options, args = parser.parse_args(real_args)
20092033

20102034
if options.version:
20112035
print 'bpython version', __version__,
@@ -2028,7 +2052,7 @@ def main(args=None):
20282052
loadini(OPTS, options.config)
20292053

20302054
try:
2031-
o = curses.wrapper(main_curses)
2055+
o = curses.wrapper(main_curses, exec_args, options.interactive)
20322056
except:
20332057
tb = traceback.format_exc()
20342058
# I don't know why this is necessary; without it the wrapper doesn't always do

0 commit comments

Comments
 (0)