Commit 1a39110b authored by Julien Danjou's avatar Julien Danjou

monkey: allow to execute a module rather than only a script

parent 0283cffe
......@@ -9,6 +9,9 @@
- Update to Cython 0.29.7 and cffi 1.12.3.
- Add an ``--module`` option to ``gevent.monkey`` allowing to run a Python
module rather than a script.
1.5a1 (2019-05-02)
==================
......
......@@ -1060,11 +1060,14 @@ def main():
args = {}
argv = sys.argv[1:]
verbose = False
run_fn = "run_path"
script_help, patch_all_args, modules = _get_script_help()
while argv and argv[0].startswith('--'):
option = argv[0][2:]
if option == 'verbose':
verbose = True
elif option == 'module':
run_fn = "run_module"
elif option.startswith('no-') and option.replace('no-', '') in patch_all_args:
args[option[3:]] = False
elif option in patch_all_args:
......@@ -1087,15 +1090,14 @@ def main():
patch_all(**args)
if argv:
sys.argv = argv
import runpy
sys.argv = argv
# Use runpy.run_path to closely (exactly) match what the
# interpreter does given 'python <path>'. This includes allowing
# passing .pyc/.pyo files and packages with a __main__ and
# potentially even zip files. Previously we used exec, which only
# worked if we directly read a python source file.
runpy.run_path(sys.argv[0],
run_name='__main__')
getattr(runpy, run_fn)(sys.argv[0], run_name='__main__')
else:
print(script_help)
......@@ -1111,19 +1113,25 @@ def _get_script_help():
modules = [x for x in patch_all_args if 'patch_' + x in globals()]
script_help = """gevent.monkey - monkey patch the standard modules to use gevent.
USAGE: ``python -m gevent.monkey [MONKEY OPTIONS] script [SCRIPT OPTIONS]``
USAGE: ``python -m gevent.monkey [MONKEY OPTIONS] [--module] (script|module) [SCRIPT OPTIONS]``
If no OPTIONS present, monkey patches all the modules it can patch.
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
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
case only the modules specified on the command line will be patched.
The default behavior is to execute the script passed as argument. If you with
to run a module instead, pass the `--module` argument before the module name.
.. 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.
.. versionchanged:: 1.5
The `--module` option has been added.
MONKEY OPTIONS: ``--verbose %s``""" % ', '.join('--[no-]%s' % m for m in modules)
return script_help, patch_all_args, modules
......
......@@ -17,15 +17,21 @@ class TestRun(unittest.TestCase):
def tearDown(self):
os.chdir(self.cwd)
def _run(self, script):
def _run(self, script, module=False):
env = os.environ.copy()
env['PYTHONWARNINGS'] = 'ignore'
args = [sys.executable, '-m', 'gevent.monkey', script, 'patched']
args = [sys.executable, '-m', 'gevent.monkey']
if module:
args.append('--module')
args += [script, 'patched']
p = Popen(args, stdout=PIPE, stderr=PIPE, env=env)
gout, gerr = p.communicate()
self.assertEqual(0, p.returncode, (gout, gerr))
args = [sys.executable, script, 'stdlib']
if module:
args = [sys.executable, "-m", script, 'stdlib']
else:
args = [sys.executable, script, 'stdlib']
p = Popen(args, stdout=PIPE, stderr=PIPE)
pout, perr = p.communicate()
......@@ -48,6 +54,13 @@ class TestRun(unittest.TestCase):
self.assertTrue(lines[0].endswith('__main__.py'), lines[0])
self.assertEqual(lines[1], '__main__')
def test_run_module(self):
# Run a __main__ inside a module
lines, _ = self._run('monkey_package', module=True)
self.assertTrue(lines[0].endswith('__main__.py'), lines[0])
self.assertEqual(lines[1], '__main__')
def test_issue_302(self):
lines, _ = self._run(os.path.join('monkey_package', 'issue302monkey.py'))
......
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