Commit 6b4990f6 authored by Kirill Smelkov's avatar Kirill Smelkov

gpython: Fix pymain to properly setup sys.path[0]

Pymain was not adding e.g. directory of executed file to sys.path, and
as the result if there were e.g. 2 files

	dir/	# imports world

running `gpython dir/` would fail to import world.

The case for interactive console was also failing to setup sys.argv as
empty, so it was containing ['/path/to/gpython']. It was also, contrary
to standard python, unconditionally showing '>>>' prompt even when stdin
was not a tty.

Fix all that and add a test to cover pymain functionality.
parent 411bdd7d
include COPYING README.rst CHANGELOG.rst tox.ini
recursive-include golang/testdata *.py
recursive-include gpython/testdata *.py
......@@ -43,15 +43,37 @@ from __future__ import print_function
# argv is what comes via `...` without first [0] for python.
def pymain(argv):
import sys, code, runpy, six
from os.path import dirname
from six.moves import input as raw_input
# interactive console
if not argv:
sys.argv = ['']
sys.path.insert(0, '') # cwd
# like code.interact() but with overridden console.raw_input _and_
# readline imported (code.interact mutually excludes those two).
import readline # enable interactive editing
except ImportError:
console = code.InteractiveConsole()
def _(prompt):
# python behaviour: don't print '>>>' if stdin is not a tty
# (builtin raw_input always prints prompt)
if not sys.stdin.isatty():
return raw_input(prompt)
console.raw_input = _
# -c command
if argv[0] == '-c':
sys.argv = argv[0:1] + argv[2:] # python leaves '-c' as argv[0]
sys.path.insert(0, '') # cwd
# exec with the same globals `python -c ...` does
g = {'__name__': '__main__',
......@@ -63,7 +85,9 @@ def pymain(argv):
elif argv[0] == '-m':
# search sys.path for module and run corresponding .py file as script
sys.argv = argv[1:]
runpy.run_module(sys.argv[0], init_globals={'__doc__': None}, run_name='__main__')
sys.path.insert(0, '') # cwd
runpy.run_module(sys.argv[0], init_globals={'__doc__': None},
run_name='__main__', alter_sys=True)
elif argv[0].startswith('-'):
print("unknown option: '%s'" % argv[0], file=sys.stderr)
......@@ -73,6 +97,7 @@ def pymain(argv):
sys.argv = argv
filepath = argv[0]
sys.path.insert(0, dirname(filepath))
# exec with same globals `python` does
# XXX use runpy.run_path() instead?
......@@ -81,11 +81,53 @@ def test_gevent_activated():
if sys.hexversion >= 0x03070000: # >= 3.7.0
assert patched('queue')
# pyrun runs `sys.executable argv... <stdin` and returns its output.
def pyrun(argv, stdin=None, **kw):
from subprocess import Popen, PIPE
argv = [sys.executable] + argv
p = Popen(argv, stdin=(PIPE if stdin else None), stdout=PIPE, stderr=PIPE, **kw)
stdout, stderr = p.communicate(stdin)
if p.returncode:
raise RuntimeError(' '.join(argv) + '\n' + (stderr and str(stderr) or '(failed)'))
return stdout
def test_executable():
# sys.executable must point to gpython and we must be able to execute it.
assert 'gpython' in sys.executable
out = subprocess.check_output([sys.executable, '-c', 'import sys; print(sys.version)'])
out = pyrun(['-c', 'import sys; print(sys.version)'])
assert ('[GPython %s]' % golang.__version__) in str(out)
# TODO test_pymain (it is not gpython_only)
# b converts s to UTF-8 encoded bytes.
def b(s):
from golang.strconv import _bstr
s, _ = _bstr(s)
return s
# verify pymain.
# !gpython_only to make sure we get the same output when run via pymain (under
# gpython) and plain python (!gpython).
def test_pymain():
from os.path import join, dirname, realpath
here = dirname(__file__)
testdata = join(dirname(__file__), 'testdata')
# interactive
_ = pyrun([], stdin=b'import hello\n', cwd=testdata)
assert _ == b"hello\nworld\n['']\n"
# -c
_ = pyrun(['-c', 'import hello', 'abc', 'def'], cwd=testdata)
assert _ == b"hello\nworld\n['-c', 'abc', 'def']\n"
# -m
_ = pyrun(['-m', 'hello', 'abc', 'def'], cwd=testdata)
# realpath rewrites e.g. `local/lib -> lib` if local/lib is symlink
hellopy = realpath(join(testdata, ''))
assert _ == b"hello\nworld\n['%s', 'abc', 'def']\n" % b(hellopy)
# file
_ = pyrun(['testdata/', 'abc', 'def'], cwd=here)
assert _ == b"hello\nworld\n['testdata/', 'abc', 'def']\n"
# imports should be resolved relative to main py file
import world
# sys.argv
import sys
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment