sys.argv = [sys.argv[0]] + rest
try:
- if opts.module is not None:
- import runpy
+ import runpy
+ if opts.module is not None:
runpy.run_module(opts.module, run_name="__main__", alter_sys=True)
else:
assert path is not None
- with open(path) as f:
- # Execute the script in our namespace instead of creating
- # a new one so that something that tries to import __main__
- # (e.g. the unittest module) will see names defined in the
- # script instead of just those defined in this module.
- global __file__
- __file__ = path
- # If __package__ is defined, imports may be incorrectly
- # interpreted as relative to this module.
- global __package__
- del __package__
- exec_in(f.read(), globals(), globals())
+ runpy.run_path(path, run_name="__main__")
except SystemExit as e:
gen_log.info("Script exited with status %s", e.code)
except Exception as e:
class AutoreloadTest(unittest.TestCase):
def setUp(self):
+ # When these tests fail the output sometimes exceeds the default maxDiff.
+ self.maxDiff = 1024
+
self.path = mkdtemp()
# Each test app runs itself twice via autoreload. The first time it manually triggers
}
)
- with self.subTest(mode="module"):
- # In module mode, the path is set to the parent directory and we can import testapp.
- # Also, the __spec__.name is set to the fully qualified module name.
- out = self.run_subprocess([sys.executable, "-m", "testapp"])
- self.assertEqual(
- out,
- (
- "import testapp succeeded\n"
- + "Starting __name__='__main__', __spec__.name=testapp.__main__\n"
- )
- * 2,
- )
-
- with self.subTest(mode="file"):
- # When the __main__.py file is run directly, there is no qualified module spec and we
- # cannot import testapp.
- out = self.run_subprocess([sys.executable, "testapp/__main__.py"])
- self.assertEqual(
- out,
- "import testapp failed\nStarting __name__='__main__', __spec__.name=None\n"
- * 2,
- )
-
- with self.subTest(mode="directory"):
- # Running as a directory finds __main__.py like a module. It does not manipulate
- # sys.path but it does set a spec with a name of exactly __main__.
- out = self.run_subprocess([sys.executable, "testapp"])
- self.assertEqual(
- out,
- "import testapp failed\nStarting __name__='__main__', __spec__.name=__main__\n"
- * 2,
- )
+ # The autoreload wrapper should support all the same modes as the python interpreter.
+ # The wrapper itself should have no effect on this test so we try all modes with and
+ # without it.
+ for wrapper in [False, True]:
+ with self.subTest(wrapper=wrapper):
+ with self.subTest(mode="module"):
+ if wrapper:
+ base_args = [sys.executable, "-m", "tornado.autoreload"]
+ else:
+ base_args = [sys.executable]
+ # In module mode, the path is set to the parent directory and we can import
+ # testapp. Also, the __spec__.name is set to the fully qualified module name.
+ out = self.run_subprocess(base_args + ["-m", "testapp"])
+ self.assertEqual(
+ out,
+ (
+ "import testapp succeeded\n"
+ + "Starting __name__='__main__', __spec__.name=testapp.__main__\n"
+ )
+ * 2,
+ )
+
+ with self.subTest(mode="file"):
+ out = self.run_subprocess(base_args + ["testapp/__main__.py"])
+ # In file mode, we do not expect the path to be set so we can import testapp,
+ # but when the wrapper is used the -m argument to the python interpreter
+ # does this for us.
+ expect_import = (
+ "import testapp succeeded"
+ if wrapper
+ else "import testapp failed"
+ )
+ # In file mode there is no qualified module spec.
+ self.assertEqual(
+ out,
+ f"{expect_import}\nStarting __name__='__main__', __spec__.name=None\n"
+ * 2,
+ )
+
+ with self.subTest(mode="directory"):
+ # Running as a directory finds __main__.py like a module. It does not manipulate
+ # sys.path but it does set a spec with a name of exactly __main__.
+ out = self.run_subprocess(base_args + ["testapp"])
+ expect_import = (
+ "import testapp succeeded"
+ if wrapper
+ else "import testapp failed"
+ )
+ self.assertEqual(
+ out,
+ f"{expect_import}\nStarting __name__='__main__', __spec__.name=__main__\n"
+ * 2,
+ )
def test_reload_wrapper_preservation(self):
# This test verifies that when `python -m tornado.autoreload`
def test_reload_wrapper_args(self):
main = """\
+import os
import sys
print(os.path.basename(sys.argv[0]))