Commit 9a198e54 authored by Jason Madden's avatar Jason Madden

Use runpy.run_path for 'python -m gevent.monkey'.

This lets us run packages and compiled files, as well as automatically taking care of all the import related globals like __file__ and __package__.

Fixes #1157
parent 892bd17b
...@@ -60,6 +60,10 @@ Enhancements ...@@ -60,6 +60,10 @@ Enhancements
time-sensitive parts of the hub itself. Please report any time-sensitive parts of the hub itself. Please report any
compatibility issues. compatibility issues.
- ``python -m gevent.monkey <script>`` accepts more values for
``<script>``, including paths to packages or compiled bytecode.
Reported in :issue:`1157` by Eddie Linder.
Monitoring and Debugging Monitoring and Debugging
------------------------ ------------------------
......
...@@ -766,13 +766,13 @@ def main(): ...@@ -766,13 +766,13 @@ def main():
patch_all(**args) patch_all(**args)
if argv: if argv:
sys.argv = argv sys.argv = argv
__package__ = None import runpy
assert __package__ is None # Use runpy.run_path to closely (exactly) match what the
globals()['__file__'] = sys.argv[0] # issue #302 # interpreter does given 'python <path>'. This includes allowing
globals()['__package__'] = None # issue #975: make script be its own package # passing .pyc/.pyo files and packages with a __main__ and
with open(sys.argv[0]) as f: # potentially even zip files. Previously we used exec, which only
# Be sure to exec in globals to avoid import pollution. Also #975. # worked if we directly read a python source file.
exec(f.read(), globals()) runpy.run_path(sys.argv[0], run_name='__main__')
else: else:
print(script_help) print(script_help)
...@@ -795,6 +795,12 @@ You can exclude a module with --no-module, e.g. --no-thread. You can ...@@ -795,6 +795,12 @@ You can exclude a module with --no-module, e.g. --no-thread. You can
specify a module to patch with --module, e.g. --socket. In the latter specify a module to patch with --module, e.g. --socket. In the latter
case only the modules specified on the command line will be patched. case only the modules specified on the command line will be patched.
.. versionchanged:: 1.3b1
The *script* argument can now be any argument that can be passed to `runpy.run_path`,
just like the interpreter itself does, for example a package directory containing ``__main__.py``.
Previously it had to be the path to
a .py source file.
MONKEY OPTIONS: --verbose %s""" % ', '.join('--[no-]%s' % m for m in modules) MONKEY OPTIONS: --verbose %s""" % ', '.join('--[no-]%s' % m for m in modules)
return script_help, patch_all_args, modules return script_help, patch_all_args, modules
......
from __future__ import print_function
# This file makes this directory into a package.
# it exists to test 'python -m gevent.monkey monkey_package'
print(__file__)
print(__name__)
...@@ -3,11 +3,24 @@ import sys ...@@ -3,11 +3,24 @@ import sys
if 'gevent' not in sys.modules: if 'gevent' not in sys.modules:
from subprocess import Popen from subprocess import Popen
from subprocess import PIPE
# Run a simple script
args = [sys.executable, '-m', 'gevent.monkey', __file__] args = [sys.executable, '-m', 'gevent.monkey', __file__]
p = Popen(args) p = Popen(args)
code = p.wait() code = p.wait()
assert code == 0, code assert code == 0, code
# Run a __main__ inside a package.
args = [sys.executable, '-m', 'gevent.monkey', 'monkey_package']
p = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
lines = out.splitlines()
assert lines[0].endswith(b'__main__.py'), (out, err)
assert lines[1] == b'__main__', (lines, out, err)
# Python 3.7 tends to produce some inscrutable
# warning from importlib._bootstrap.py on stderr
# "ImportWarning: can't resolve package from __spec__ or __package__".
# So we don't check that err is empty.
else: else:
from textwrap import dedent from textwrap import dedent
......
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