{
    "file_diffs": [
        {
            "old_file_content": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Automatically restart the server when a source file is modified.\n\nMost applications should not access this module directly.  Instead,\npass the keyword argument ``autoreload=True`` to the\n`tornado.web.Application` constructor (or ``debug=True``, which\nenables this setting and several others).  This will enable autoreload\nmode as well as checking for changes to templates and static\nresources.  Note that restarting is a destructive operation and any\nrequests in progress will be aborted when the process restarts.  (If\nyou want to disable autoreload while using other debug-mode features,\npass both ``debug=True`` and ``autoreload=False``).\n\nThis module can also be used as a command-line wrapper around scripts\nsuch as unit test runners.  See the `main` method for details.\n\nThe command-line wrapper and Application debug modes can be used together.\nThis combination is encouraged as the wrapper catches syntax errors and\nother import-time failures, while debug mode catches changes once\nthe server has started.\n\nThis module depends on `.IOLoop`, so it will not work in WSGI applications\nand Google App Engine.  It also will not work correctly when `.HTTPServer`'s\nmulti-process mode is used.\n\nReloading loses any Python interpreter command-line arguments (e.g. ``-u``)\nbecause it re-executes Python using ``sys.executable`` and ``sys.argv``.\nAdditionally, modifying these variables will cause reloading to behave\nincorrectly.\n\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\nimport os\nimport sys\n\n# sys.path handling\n# -----------------\n#\n# If a module is run with \"python -m\", the current directory (i.e. \"\")\n# is automatically prepended to sys.path, but not if it is run as\n# \"path/to/file.py\".  The processing for \"-m\" rewrites the former to\n# the latter, so subsequent executions won't have the same path as the\n# original.\n#\n# Conversely, when run as path/to/file.py, the directory containing\n# file.py gets added to the path, which can cause confusion as imports\n# may become relative in spite of the future import.\n#\n# We address the former problem by setting the $PYTHONPATH environment\n# variable before re-execution so the new process will see the correct\n# path.  We attempt to address the latter problem when tornado.autoreload\n# is run as __main__, although we can't fix the general case because\n# we cannot reliably reconstruct the original command line\n# (http://bugs.python.org/issue14208).\n\nif __name__ == \"__main__\":\n    # This sys.path manipulation must come before our imports (as much\n    # as possible - if we introduced a tornado.sys or tornado.os\n    # module we'd be in trouble), or else our imports would become\n    # relative again despite the future import.\n    #\n    # There is a separate __main__ block at the end of the file to call main().\n    if sys.path[0] == os.path.dirname(__file__):\n        del sys.path[0]\n\nimport functools\nimport logging\nimport os\nimport pkgutil  # type: ignore\nimport sys\nimport traceback\nimport types\nimport subprocess\nimport weakref\n\nfrom tornado import ioloop\nfrom tornado.log import gen_log\nfrom tornado import process\nfrom tornado.util import exec_in\n\ntry:\n    import signal\nexcept ImportError:\n    signal = None\n\n# os.execv is broken on Windows and can't properly parse command line\n# arguments and executable name if they contain whitespaces. subprocess\n# fixes that behavior.\n_has_execv = sys.platform != 'win32'\n\n_watched_files = set()\n_reload_hooks = []\n_reload_attempted = False\n_io_loops = weakref.WeakKeyDictionary()  # type: ignore\n\n\ndef start(check_time=500):\n    \"\"\"Begins watching source files for changes.\n\n    .. versionchanged:: 5.0\n       The ``io_loop`` argument (deprecated since version 4.1) has been removed.\n    \"\"\"\n    io_loop = ioloop.IOLoop.current()\n    if io_loop in _io_loops:\n        return\n    _io_loops[io_loop] = True\n    if len(_io_loops) > 1:\n        gen_log.warning(\"tornado.autoreload started more than once in the same process\")\n    modify_times = {}\n    callback = functools.partial(_reload_on_update, modify_times)\n    scheduler = ioloop.PeriodicCallback(callback, check_time)\n    scheduler.start()\n\n\ndef wait():\n    \"\"\"Wait for a watched file to change, then restart the process.\n\n    Intended to be used at the end of scripts like unit test runners,\n    to run the tests again after any source file changes (but see also\n    the command-line interface in `main`)\n    \"\"\"\n    io_loop = ioloop.IOLoop()\n    start(io_loop)\n    io_loop.start()\n\n\ndef watch(filename):\n    \"\"\"Add a file to the watch list.\n\n    All imported modules are watched by default.\n    \"\"\"\n    _watched_files.add(filename)\n\n\ndef add_reload_hook(fn):\n    \"\"\"Add a function to be called before reloading the process.\n\n    Note that for open file and socket handles it is generally\n    preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or\n    ``tornado.platform.auto.set_close_exec``) instead\n    of using a reload hook to close them.\n    \"\"\"\n    _reload_hooks.append(fn)\n\n\ndef _reload_on_update(modify_times):\n    if _reload_attempted:\n        # We already tried to reload and it didn't work, so don't try again.\n        return\n    if process.task_id() is not None:\n        # We're in a child process created by fork_processes.  If child\n        # processes restarted themselves, they'd all restart and then\n        # all call fork_processes again.\n        return\n    for module in list(sys.modules.values()):\n        # Some modules play games with sys.modules (e.g. email/__init__.py\n        # in the standard library), and occasionally this can cause strange\n        # failures in getattr.  Just ignore anything that's not an ordinary\n        # module.\n        if not isinstance(module, types.ModuleType):\n            continue\n        path = getattr(module, \"__file__\", None)\n        if not path:\n            continue\n        if path.endswith(\".pyc\") or path.endswith(\".pyo\"):\n            path = path[:-1]\n        _check_file(modify_times, path)\n    for path in _watched_files:\n        _check_file(modify_times, path)\n\n\ndef _check_file(modify_times, path):\n    try:\n        modified = os.stat(path).st_mtime\n    except Exception:\n        return\n    if path not in modify_times:\n        modify_times[path] = modified\n        return\n    if modify_times[path] != modified:\n        gen_log.info(\"%s modified; restarting server\", path)\n        _reload()\n\n\ndef _reload():\n    global _reload_attempted\n    _reload_attempted = True\n    for fn in _reload_hooks:\n        fn()\n    if hasattr(signal, \"setitimer\"):\n        # Clear the alarm signal set by\n        # ioloop.set_blocking_log_threshold so it doesn't fire\n        # after the exec.\n        signal.setitimer(signal.ITIMER_REAL, 0, 0)\n    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty\n    # string, we were (probably) invoked with -m and the effective path\n    # is about to change on re-exec.  Add the current directory to $PYTHONPATH\n    # to ensure that the new process sees the same path we did.\n    path_prefix = '.' + os.pathsep\n    if (sys.path[0] == '' and\n            not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):\n        os.environ[\"PYTHONPATH\"] = (path_prefix +\n                                    os.environ.get(\"PYTHONPATH\", \"\"))\n    if not _has_execv:\n        subprocess.Popen([sys.executable] + sys.argv)\n        sys.exit(0)\n    else:\n        try:\n            os.execv(sys.executable, [sys.executable] + sys.argv)\n        except OSError:\n            # Mac OS X versions prior to 10.6 do not support execv in\n            # a process that contains multiple threads.  Instead of\n            # re-executing in the current process, start a new one\n            # and cause the current process to exit.  This isn't\n            # ideal since the new process is detached from the parent\n            # terminal and thus cannot easily be killed with ctrl-C,\n            # but it's better than not being able to autoreload at\n            # all.\n            # Unfortunately the errno returned in this case does not\n            # appear to be consistent, so we can't easily check for\n            # this error specifically.\n            os.spawnv(os.P_NOWAIT, sys.executable,\n                      [sys.executable] + sys.argv)\n            # At this point the IOLoop has been closed and finally\n            # blocks will experience errors if we allow the stack to\n            # unwind, so just exit uncleanly.\n            os._exit(0)\n\n\n_USAGE = \"\"\"\\\nUsage:\n  python -m tornado.autoreload -m module.to.run [args...]\n  python -m tornado.autoreload path/to/script.py [args...]\n\"\"\"\n\n\ndef main():\n    \"\"\"Command-line wrapper to re-run a script whenever its source changes.\n\n    Scripts may be specified by filename or module name::\n\n        python -m tornado.autoreload -m tornado.test.runtests\n        python -m tornado.autoreload tornado/test/runtests.py\n\n    Running a script with this wrapper is similar to calling\n    `tornado.autoreload.wait` at the end of the script, but this wrapper\n    can catch import-time problems like syntax errors that would otherwise\n    prevent the script from reaching its call to `wait`.\n    \"\"\"\n    original_argv = sys.argv\n    sys.argv = sys.argv[:]\n    if len(sys.argv) >= 3 and sys.argv[1] == \"-m\":\n        mode = \"module\"\n        module = sys.argv[2]\n        del sys.argv[1:3]\n    elif len(sys.argv) >= 2:\n        mode = \"script\"\n        script = sys.argv[1]\n        sys.argv = sys.argv[1:]\n    else:\n        print(_USAGE, file=sys.stderr)\n        sys.exit(1)\n\n    try:\n        if mode == \"module\":\n            import runpy\n            runpy.run_module(module, run_name=\"__main__\", alter_sys=True)\n        elif mode == \"script\":\n            with open(script) as f:\n                # Execute the script in our namespace instead of creating\n                # a new one so that something that tries to import __main__\n                # (e.g. the unittest module) will see names defined in the\n                # script instead of just those defined in this module.\n                global __file__\n                __file__ = script\n                # If __package__ is defined, imports may be incorrectly\n                # interpreted as relative to this module.\n                global __package__\n                del __package__\n                exec_in(f.read(), globals(), globals())\n    except SystemExit as e:\n        logging.basicConfig()\n        gen_log.info(\"Script exited with status %s\", e.code)\n    except Exception as e:\n        logging.basicConfig()\n        gen_log.warning(\"Script exited with uncaught exception\", exc_info=True)\n        # If an exception occurred at import time, the file with the error\n        # never made it into sys.modules and so we won't know to watch it.\n        # Just to make sure we've covered everything, walk the stack trace\n        # from the exception and watch every file.\n        for (filename, lineno, name, line) in traceback.extract_tb(sys.exc_info()[2]):\n            watch(filename)\n        if isinstance(e, SyntaxError):\n            # SyntaxErrors are special:  their innermost stack frame is fake\n            # so extract_tb won't see it and we have to get the filename\n            # from the exception object.\n            watch(e.filename)\n    else:\n        logging.basicConfig()\n        gen_log.info(\"Script exited normally\")\n    # restore sys.argv so subsequent executions will include autoreload\n    sys.argv = original_argv\n\n    if mode == 'module':\n        # runpy did a fake import of the module as __main__, but now it's\n        # no longer in sys.modules.  Figure out where it is and watch it.\n        loader = pkgutil.get_loader(module)\n        if loader is not None:\n            watch(loader.get_filename())\n\n    wait()\n\n\nif __name__ == \"__main__\":\n    # See also the other __main__ block at the top of the file, which modifies\n    # sys.path before our imports\n    main()\n",
            "new_file_content": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Automatically restart the server when a source file is modified.\n\nMost applications should not access this module directly.  Instead,\npass the keyword argument ``autoreload=True`` to the\n`tornado.web.Application` constructor (or ``debug=True``, which\nenables this setting and several others).  This will enable autoreload\nmode as well as checking for changes to templates and static\nresources.  Note that restarting is a destructive operation and any\nrequests in progress will be aborted when the process restarts.  (If\nyou want to disable autoreload while using other debug-mode features,\npass both ``debug=True`` and ``autoreload=False``).\n\nThis module can also be used as a command-line wrapper around scripts\nsuch as unit test runners.  See the `main` method for details.\n\nThe command-line wrapper and Application debug modes can be used together.\nThis combination is encouraged as the wrapper catches syntax errors and\nother import-time failures, while debug mode catches changes once\nthe server has started.\n\nThis module depends on `.IOLoop`, so it will not work in WSGI applications\nand Google App Engine.  It also will not work correctly when `.HTTPServer`'s\nmulti-process mode is used.\n\nReloading loses any Python interpreter command-line arguments (e.g. ``-u``)\nbecause it re-executes Python using ``sys.executable`` and ``sys.argv``.\nAdditionally, modifying these variables will cause reloading to behave\nincorrectly.\n\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\nimport os\nimport sys\n\n# sys.path handling\n# -----------------\n#\n# If a module is run with \"python -m\", the current directory (i.e. \"\")\n# is automatically prepended to sys.path, but not if it is run as\n# \"path/to/file.py\".  The processing for \"-m\" rewrites the former to\n# the latter, so subsequent executions won't have the same path as the\n# original.\n#\n# Conversely, when run as path/to/file.py, the directory containing\n# file.py gets added to the path, which can cause confusion as imports\n# may become relative in spite of the future import.\n#\n# We address the former problem by reconstructing the original command\n# line (Python >= 3.4) or by setting the $PYTHONPATH environment\n# variable (Python < 3.4) before re-execution so the new process will\n# see the correct path.  We attempt to address the latter problem when\n# tornado.autoreload is run as __main__.\n\nif __name__ == \"__main__\":\n    # This sys.path manipulation must come before our imports (as much\n    # as possible - if we introduced a tornado.sys or tornado.os\n    # module we'd be in trouble), or else our imports would become\n    # relative again despite the future import.\n    #\n    # There is a separate __main__ block at the end of the file to call main().\n    if sys.path[0] == os.path.dirname(__file__):\n        del sys.path[0]\n\nimport functools\nimport logging\nimport os\nimport pkgutil  # type: ignore\nimport sys\nimport traceback\nimport types\nimport subprocess\nimport weakref\n\nfrom tornado import ioloop\nfrom tornado.log import gen_log\nfrom tornado import process\nfrom tornado.util import exec_in\n\ntry:\n    import signal\nexcept ImportError:\n    signal = None\n\n# os.execv is broken on Windows and can't properly parse command line\n# arguments and executable name if they contain whitespaces. subprocess\n# fixes that behavior.\n_has_execv = sys.platform != 'win32'\n\n_watched_files = set()\n_reload_hooks = []\n_reload_attempted = False\n_io_loops = weakref.WeakKeyDictionary()  # type: ignore\n\n\ndef start(check_time=500):\n    \"\"\"Begins watching source files for changes.\n\n    .. versionchanged:: 5.0\n       The ``io_loop`` argument (deprecated since version 4.1) has been removed.\n    \"\"\"\n    io_loop = ioloop.IOLoop.current()\n    if io_loop in _io_loops:\n        return\n    _io_loops[io_loop] = True\n    if len(_io_loops) > 1:\n        gen_log.warning(\"tornado.autoreload started more than once in the same process\")\n    modify_times = {}\n    callback = functools.partial(_reload_on_update, modify_times)\n    scheduler = ioloop.PeriodicCallback(callback, check_time)\n    scheduler.start()\n\n\ndef wait():\n    \"\"\"Wait for a watched file to change, then restart the process.\n\n    Intended to be used at the end of scripts like unit test runners,\n    to run the tests again after any source file changes (but see also\n    the command-line interface in `main`)\n    \"\"\"\n    io_loop = ioloop.IOLoop()\n    start(io_loop)\n    io_loop.start()\n\n\ndef watch(filename):\n    \"\"\"Add a file to the watch list.\n\n    All imported modules are watched by default.\n    \"\"\"\n    _watched_files.add(filename)\n\n\ndef add_reload_hook(fn):\n    \"\"\"Add a function to be called before reloading the process.\n\n    Note that for open file and socket handles it is generally\n    preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or\n    ``tornado.platform.auto.set_close_exec``) instead\n    of using a reload hook to close them.\n    \"\"\"\n    _reload_hooks.append(fn)\n\n\ndef _reload_on_update(modify_times):\n    if _reload_attempted:\n        # We already tried to reload and it didn't work, so don't try again.\n        return\n    if process.task_id() is not None:\n        # We're in a child process created by fork_processes.  If child\n        # processes restarted themselves, they'd all restart and then\n        # all call fork_processes again.\n        return\n    for module in list(sys.modules.values()):\n        # Some modules play games with sys.modules (e.g. email/__init__.py\n        # in the standard library), and occasionally this can cause strange\n        # failures in getattr.  Just ignore anything that's not an ordinary\n        # module.\n        if not isinstance(module, types.ModuleType):\n            continue\n        path = getattr(module, \"__file__\", None)\n        if not path:\n            continue\n        if path.endswith(\".pyc\") or path.endswith(\".pyo\"):\n            path = path[:-1]\n        _check_file(modify_times, path)\n    for path in _watched_files:\n        _check_file(modify_times, path)\n\n\ndef _check_file(modify_times, path):\n    try:\n        modified = os.stat(path).st_mtime\n    except Exception:\n        return\n    if path not in modify_times:\n        modify_times[path] = modified\n        return\n    if modify_times[path] != modified:\n        gen_log.info(\"%s modified; restarting server\", path)\n        _reload()\n\n\ndef _reload():\n    global _reload_attempted\n    _reload_attempted = True\n    for fn in _reload_hooks:\n        fn()\n    if hasattr(signal, \"setitimer\"):\n        # Clear the alarm signal set by\n        # ioloop.set_blocking_log_threshold so it doesn't fire\n        # after the exec.\n        signal.setitimer(signal.ITIMER_REAL, 0, 0)\n    # sys.path fixes: see comments at top of file.  If __main__.__spec__\n    # exists, we were invoked with -m and the effective path is about to\n    # change on re-exec.  Reconstruct the original command line to\n    # ensure that the new process sees the same path we did.  If\n    # __spec__ is not available (Python < 3.4), check instead if\n    # sys.path[0] is an empty string and add the current directory to\n    # $PYTHONPATH.\n    spec = getattr(sys.modules['__main__'], '__spec__', None)\n    if spec:\n        argv = ['-m', spec.name] + sys.argv[1:]\n    else:\n        argv = sys.argv\n        path_prefix = '.' + os.pathsep\n        if (sys.path[0] == '' and\n                not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):\n            os.environ[\"PYTHONPATH\"] = (path_prefix +\n                                        os.environ.get(\"PYTHONPATH\", \"\"))\n    if not _has_execv:\n        subprocess.Popen([sys.executable] + argv)\n        sys.exit(0)\n    else:\n        try:\n            os.execv(sys.executable, [sys.executable] + argv)\n        except OSError:\n            # Mac OS X versions prior to 10.6 do not support execv in\n            # a process that contains multiple threads.  Instead of\n            # re-executing in the current process, start a new one\n            # and cause the current process to exit.  This isn't\n            # ideal since the new process is detached from the parent\n            # terminal and thus cannot easily be killed with ctrl-C,\n            # but it's better than not being able to autoreload at\n            # all.\n            # Unfortunately the errno returned in this case does not\n            # appear to be consistent, so we can't easily check for\n            # this error specifically.\n            os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable] + argv)\n            # At this point the IOLoop has been closed and finally\n            # blocks will experience errors if we allow the stack to\n            # unwind, so just exit uncleanly.\n            os._exit(0)\n\n\n_USAGE = \"\"\"\\\nUsage:\n  python -m tornado.autoreload -m module.to.run [args...]\n  python -m tornado.autoreload path/to/script.py [args...]\n\"\"\"\n\n\ndef main():\n    \"\"\"Command-line wrapper to re-run a script whenever its source changes.\n\n    Scripts may be specified by filename or module name::\n\n        python -m tornado.autoreload -m tornado.test.runtests\n        python -m tornado.autoreload tornado/test/runtests.py\n\n    Running a script with this wrapper is similar to calling\n    `tornado.autoreload.wait` at the end of the script, but this wrapper\n    can catch import-time problems like syntax errors that would otherwise\n    prevent the script from reaching its call to `wait`.\n    \"\"\"\n    original_argv = sys.argv\n    sys.argv = sys.argv[:]\n    if len(sys.argv) >= 3 and sys.argv[1] == \"-m\":\n        mode = \"module\"\n        module = sys.argv[2]\n        del sys.argv[1:3]\n    elif len(sys.argv) >= 2:\n        mode = \"script\"\n        script = sys.argv[1]\n        sys.argv = sys.argv[1:]\n    else:\n        print(_USAGE, file=sys.stderr)\n        sys.exit(1)\n\n    try:\n        if mode == \"module\":\n            import runpy\n            runpy.run_module(module, run_name=\"__main__\", alter_sys=True)\n        elif mode == \"script\":\n            with open(script) as f:\n                # Execute the script in our namespace instead of creating\n                # a new one so that something that tries to import __main__\n                # (e.g. the unittest module) will see names defined in the\n                # script instead of just those defined in this module.\n                global __file__\n                __file__ = script\n                # If __package__ is defined, imports may be incorrectly\n                # interpreted as relative to this module.\n                global __package__\n                del __package__\n                exec_in(f.read(), globals(), globals())\n    except SystemExit as e:\n        logging.basicConfig()\n        gen_log.info(\"Script exited with status %s\", e.code)\n    except Exception as e:\n        logging.basicConfig()\n        gen_log.warning(\"Script exited with uncaught exception\", exc_info=True)\n        # If an exception occurred at import time, the file with the error\n        # never made it into sys.modules and so we won't know to watch it.\n        # Just to make sure we've covered everything, walk the stack trace\n        # from the exception and watch every file.\n        for (filename, lineno, name, line) in traceback.extract_tb(sys.exc_info()[2]):\n            watch(filename)\n        if isinstance(e, SyntaxError):\n            # SyntaxErrors are special:  their innermost stack frame is fake\n            # so extract_tb won't see it and we have to get the filename\n            # from the exception object.\n            watch(e.filename)\n    else:\n        logging.basicConfig()\n        gen_log.info(\"Script exited normally\")\n    # restore sys.argv so subsequent executions will include autoreload\n    sys.argv = original_argv\n\n    if mode == 'module':\n        # runpy did a fake import of the module as __main__, but now it's\n        # no longer in sys.modules.  Figure out where it is and watch it.\n        loader = pkgutil.get_loader(module)\n        if loader is not None:\n            watch(loader.get_filename())\n\n    wait()\n\n\nif __name__ == \"__main__\":\n    # See also the other __main__ block at the top of the file, which modifies\n    # sys.path before our imports\n    main()\n",
            "header": {
                "file": {
                    "path": "tornado/autoreload.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "24deb79d",
                "new_commit_hash": "da1b100d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/autoreload.py"
            },
            "plus_file": {
                "path": "b/tornado/autoreload.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 63,
                            "length": 12
                        },
                        "new_range": {
                            "start": 63,
                            "length": 11
                        },
                        "section": "import sys"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "# file.py gets added to the path, which can cause confusion as imports",
                                "type": "context"
                            },
                            {
                                "content": "# may become relative in spite of the future import.",
                                "type": "context"
                            },
                            {
                                "content": "#",
                                "type": "context"
                            },
                            {
                                "content": "# We address the former problem by setting the $PYTHONPATH environment",
                                "type": "deleted"
                            },
                            {
                                "content": "# variable before re-execution so the new process will see the correct",
                                "type": "deleted"
                            },
                            {
                                "content": "# path.  We attempt to address the latter problem when tornado.autoreload",
                                "type": "deleted"
                            },
                            {
                                "content": "# is run as __main__, although we can't fix the general case because",
                                "type": "deleted"
                            },
                            {
                                "content": "# we cannot reliably reconstruct the original command line",
                                "type": "deleted"
                            },
                            {
                                "content": "# (http://bugs.python.org/issue14208).",
                                "type": "deleted"
                            },
                            {
                                "content": "# We address the former problem by reconstructing the original command",
                                "type": "added"
                            },
                            {
                                "content": "# line (Python >= 3.4) or by setting the $PYTHONPATH environment",
                                "type": "added"
                            },
                            {
                                "content": "# variable (Python < 3.4) before re-execution so the new process will",
                                "type": "added"
                            },
                            {
                                "content": "# see the correct path.  We attempt to address the latter problem when",
                                "type": "added"
                            },
                            {
                                "content": "# tornado.autoreload is run as __main__.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "if __name__ == \"__main__\":",
                                "type": "context"
                            },
                            {
                                "content": "    # This sys.path manipulation must come before our imports (as much",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 209,
                            "length": 21
                        },
                        "new_range": {
                            "start": 208,
                            "length": 29
                        },
                        "section": "def _reload():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        # ioloop.set_blocking_log_threshold so it doesn't fire",
                                "type": "context"
                            },
                            {
                                "content": "        # after the exec.",
                                "type": "context"
                            },
                            {
                                "content": "        signal.setitimer(signal.ITIMER_REAL, 0, 0)",
                                "type": "context"
                            },
                            {
                                "content": "    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty",
                                "type": "deleted"
                            },
                            {
                                "content": "    # string, we were (probably) invoked with -m and the effective path",
                                "type": "deleted"
                            },
                            {
                                "content": "    # is about to change on re-exec.  Add the current directory to $PYTHONPATH",
                                "type": "deleted"
                            },
                            {
                                "content": "    # to ensure that the new process sees the same path we did.",
                                "type": "deleted"
                            },
                            {
                                "content": "    path_prefix = '.' + os.pathsep",
                                "type": "deleted"
                            },
                            {
                                "content": "    if (sys.path[0] == '' and",
                                "type": "deleted"
                            },
                            {
                                "content": "            not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):",
                                "type": "deleted"
                            },
                            {
                                "content": "        os.environ[\"PYTHONPATH\"] = (path_prefix +",
                                "type": "deleted"
                            },
                            {
                                "content": "                                    os.environ.get(\"PYTHONPATH\", \"\"))",
                                "type": "deleted"
                            },
                            {
                                "content": "    # sys.path fixes: see comments at top of file.  If __main__.__spec__",
                                "type": "added"
                            },
                            {
                                "content": "    # exists, we were invoked with -m and the effective path is about to",
                                "type": "added"
                            },
                            {
                                "content": "    # change on re-exec.  Reconstruct the original command line to",
                                "type": "added"
                            },
                            {
                                "content": "    # ensure that the new process sees the same path we did.  If",
                                "type": "added"
                            },
                            {
                                "content": "    # __spec__ is not available (Python < 3.4), check instead if",
                                "type": "added"
                            },
                            {
                                "content": "    # sys.path[0] is an empty string and add the current directory to",
                                "type": "added"
                            },
                            {
                                "content": "    # $PYTHONPATH.",
                                "type": "added"
                            },
                            {
                                "content": "    spec = getattr(sys.modules['__main__'], '__spec__', None)",
                                "type": "added"
                            },
                            {
                                "content": "    if spec:",
                                "type": "added"
                            },
                            {
                                "content": "        argv = ['-m', spec.name] + sys.argv[1:]",
                                "type": "added"
                            },
                            {
                                "content": "    else:",
                                "type": "added"
                            },
                            {
                                "content": "        argv = sys.argv",
                                "type": "added"
                            },
                            {
                                "content": "        path_prefix = '.' + os.pathsep",
                                "type": "added"
                            },
                            {
                                "content": "        if (sys.path[0] == '' and",
                                "type": "added"
                            },
                            {
                                "content": "                not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):",
                                "type": "added"
                            },
                            {
                                "content": "            os.environ[\"PYTHONPATH\"] = (path_prefix +",
                                "type": "added"
                            },
                            {
                                "content": "                                        os.environ.get(\"PYTHONPATH\", \"\"))",
                                "type": "added"
                            },
                            {
                                "content": "    if not _has_execv:",
                                "type": "context"
                            },
                            {
                                "content": "        subprocess.Popen([sys.executable] + sys.argv)",
                                "type": "deleted"
                            },
                            {
                                "content": "        subprocess.Popen([sys.executable] + argv)",
                                "type": "added"
                            },
                            {
                                "content": "        sys.exit(0)",
                                "type": "context"
                            },
                            {
                                "content": "    else:",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "context"
                            },
                            {
                                "content": "            os.execv(sys.executable, [sys.executable] + sys.argv)",
                                "type": "deleted"
                            },
                            {
                                "content": "            os.execv(sys.executable, [sys.executable] + argv)",
                                "type": "added"
                            },
                            {
                                "content": "        except OSError:",
                                "type": "context"
                            },
                            {
                                "content": "            # Mac OS X versions prior to 10.6 do not support execv in",
                                "type": "context"
                            },
                            {
                                "content": "            # a process that contains multiple threads.  Instead of",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/autoreload.py",
                            "type": "function",
                            "name": "_reload",
                            "content": "def _reload():\n    global _reload_attempted\n    _reload_attempted = True\n    for fn in _reload_hooks:\n        fn()\n    if hasattr(signal, \"setitimer\"):\n        # Clear the alarm signal set by\n        # ioloop.set_blocking_log_threshold so it doesn't fire\n        # after the exec.\n        signal.setitimer(signal.ITIMER_REAL, 0, 0)\n    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty\n    # string, we were (probably) invoked with -m and the effective path\n    # is about to change on re-exec.  Add the current directory to $PYTHONPATH\n    # to ensure that the new process sees the same path we did.\n    path_prefix = '.' + os.pathsep\n    if (sys.path[0] == '' and\n            not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):\n        os.environ[\"PYTHONPATH\"] = (path_prefix +\n                                    os.environ.get(\"PYTHONPATH\", \"\"))\n    if not _has_execv:\n        subprocess.Popen([sys.executable] + sys.argv)\n        sys.exit(0)\n    else:\n        try:\n            os.execv(sys.executable, [sys.executable] + sys.argv)\n        except OSError:\n            # Mac OS X versions prior to 10.6 do not support execv in\n            # a process that contains multiple threads.  Instead of\n            # re-executing in the current process, start a new one\n            # and cause the current process to exit.  This isn't\n            # ideal since the new process is detached from the parent\n            # terminal and thus cannot easily be killed with ctrl-C,\n            # but it's better than not being able to autoreload at\n            # all.\n            # Unfortunately the errno returned in this case does not\n            # appear to be consistent, so we can't easily check for\n            # this error specifically.\n            os.spawnv(os.P_NOWAIT, sys.executable,\n                      [sys.executable] + sys.argv)\n            # At this point the IOLoop has been closed and finally\n            # blocks will experience errors if we allow the stack to\n            # unwind, so just exit uncleanly.\n            os._exit(0)",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 202,
                            "end_lineno": 244,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 236,
                            "length": 8
                        },
                        "new_range": {
                            "start": 243,
                            "length": 7
                        },
                        "section": "def _reload():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            # Unfortunately the errno returned in this case does not",
                                "type": "context"
                            },
                            {
                                "content": "            # appear to be consistent, so we can't easily check for",
                                "type": "context"
                            },
                            {
                                "content": "            # this error specifically.",
                                "type": "context"
                            },
                            {
                                "content": "            os.spawnv(os.P_NOWAIT, sys.executable,",
                                "type": "deleted"
                            },
                            {
                                "content": "                      [sys.executable] + sys.argv)",
                                "type": "deleted"
                            },
                            {
                                "content": "            os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable] + argv)",
                                "type": "added"
                            },
                            {
                                "content": "            # At this point the IOLoop has been closed and finally",
                                "type": "context"
                            },
                            {
                                "content": "            # blocks will experience errors if we allow the stack to",
                                "type": "context"
                            },
                            {
                                "content": "            # unwind, so just exit uncleanly.",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/autoreload.py",
                            "type": "function",
                            "name": "_reload",
                            "content": "def _reload():\n    global _reload_attempted\n    _reload_attempted = True\n    for fn in _reload_hooks:\n        fn()\n    if hasattr(signal, \"setitimer\"):\n        # Clear the alarm signal set by\n        # ioloop.set_blocking_log_threshold so it doesn't fire\n        # after the exec.\n        signal.setitimer(signal.ITIMER_REAL, 0, 0)\n    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty\n    # string, we were (probably) invoked with -m and the effective path\n    # is about to change on re-exec.  Add the current directory to $PYTHONPATH\n    # to ensure that the new process sees the same path we did.\n    path_prefix = '.' + os.pathsep\n    if (sys.path[0] == '' and\n            not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):\n        os.environ[\"PYTHONPATH\"] = (path_prefix +\n                                    os.environ.get(\"PYTHONPATH\", \"\"))\n    if not _has_execv:\n        subprocess.Popen([sys.executable] + sys.argv)\n        sys.exit(0)\n    else:\n        try:\n            os.execv(sys.executable, [sys.executable] + sys.argv)\n        except OSError:\n            # Mac OS X versions prior to 10.6 do not support execv in\n            # a process that contains multiple threads.  Instead of\n            # re-executing in the current process, start a new one\n            # and cause the current process to exit.  This isn't\n            # ideal since the new process is detached from the parent\n            # terminal and thus cannot easily be killed with ctrl-C,\n            # but it's better than not being able to autoreload at\n            # all.\n            # Unfortunately the errno returned in this case does not\n            # appear to be consistent, so we can't easily check for\n            # this error specifically.\n            os.spawnv(os.P_NOWAIT, sys.executable,\n                      [sys.executable] + sys.argv)\n            # At this point the IOLoop has been closed and finally\n            # blocks will experience errors if we allow the stack to\n            # unwind, so just exit uncleanly.\n            os._exit(0)",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 202,
                            "end_lineno": 244,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "",
            "new_file_content": "from __future__ import absolute_import, division, print_function\nimport os\nimport subprocess\nfrom subprocess import Popen\nimport sys\nfrom tempfile import mkdtemp\n\nfrom tornado.test.util import unittest\n\n\nMAIN = \"\"\"\\\nimport os\nimport sys\n\nfrom tornado import autoreload\n\n# This import will fail if path is not set up correctly\nimport testapp\n\nprint('Starting')\nif 'TESTAPP_STARTED' not in os.environ:\n    os.environ['TESTAPP_STARTED'] = '1'\n    sys.stdout.flush()\n    autoreload._reload()\n\"\"\"\n\n\nclass AutoreloadTest(unittest.TestCase):\n    def test_reload_module(self):\n        # Create temporary test application\n        path = mkdtemp()\n        os.mkdir(os.path.join(path, 'testapp'))\n        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()\n        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:\n            f.write(MAIN)\n\n        # Make sure the tornado module under test is available to the test\n        # application\n        pythonpath = os.getcwd()\n        if 'PYTHONPATH' in os.environ:\n            pythonpath += os.pathsep + os.environ['PYTHONPATH']\n\n        p = Popen(\n            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,\n            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),\n            universal_newlines=True)\n        out = p.communicate()[0]\n        self.assertEqual(out, 'Starting\\nStarting\\n')\n",
            "header": {
                "file": {
                    "path": "tornado/test/autoreload_test.py"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "6a9729db",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/tornado/test/autoreload_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": 48
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from __future__ import absolute_import, division, print_function",
                                "type": "added"
                            },
                            {
                                "content": "import os",
                                "type": "added"
                            },
                            {
                                "content": "import subprocess",
                                "type": "added"
                            },
                            {
                                "content": "from subprocess import Popen",
                                "type": "added"
                            },
                            {
                                "content": "import sys",
                                "type": "added"
                            },
                            {
                                "content": "from tempfile import mkdtemp",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "from tornado.test.util import unittest",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "MAIN = \"\"\"\\",
                                "type": "added"
                            },
                            {
                                "content": "import os",
                                "type": "added"
                            },
                            {
                                "content": "import sys",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "from tornado import autoreload",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "# This import will fail if path is not set up correctly",
                                "type": "added"
                            },
                            {
                                "content": "import testapp",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "print('Starting')",
                                "type": "added"
                            },
                            {
                                "content": "if 'TESTAPP_STARTED' not in os.environ:",
                                "type": "added"
                            },
                            {
                                "content": "    os.environ['TESTAPP_STARTED'] = '1'",
                                "type": "added"
                            },
                            {
                                "content": "    sys.stdout.flush()",
                                "type": "added"
                            },
                            {
                                "content": "    autoreload._reload()",
                                "type": "added"
                            },
                            {
                                "content": "\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "class AutoreloadTest(unittest.TestCase):",
                                "type": "added"
                            },
                            {
                                "content": "    def test_reload_module(self):",
                                "type": "added"
                            },
                            {
                                "content": "        # Create temporary test application",
                                "type": "added"
                            },
                            {
                                "content": "        path = mkdtemp()",
                                "type": "added"
                            },
                            {
                                "content": "        os.mkdir(os.path.join(path, 'testapp'))",
                                "type": "added"
                            },
                            {
                                "content": "        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()",
                                "type": "added"
                            },
                            {
                                "content": "        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:",
                                "type": "added"
                            },
                            {
                                "content": "            f.write(MAIN)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        # Make sure the tornado module under test is available to the test",
                                "type": "added"
                            },
                            {
                                "content": "        # application",
                                "type": "added"
                            },
                            {
                                "content": "        pythonpath = os.getcwd()",
                                "type": "added"
                            },
                            {
                                "content": "        if 'PYTHONPATH' in os.environ:",
                                "type": "added"
                            },
                            {
                                "content": "            pythonpath += os.pathsep + os.environ['PYTHONPATH']",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        p = Popen(",
                                "type": "added"
                            },
                            {
                                "content": "            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,",
                                "type": "added"
                            },
                            {
                                "content": "            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),",
                                "type": "added"
                            },
                            {
                                "content": "            universal_newlines=True)",
                                "type": "added"
                            },
                            {
                                "content": "        out = p.communicate()[0]",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(out, 'Starting\\nStarting\\n')",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "class",
                            "name": "AutoreloadTest",
                            "content": "class AutoreloadTest(unittest.TestCase):\n    def test_reload_module(self):\n        # Create temporary test application\n        path = mkdtemp()\n        os.mkdir(os.path.join(path, 'testapp'))\n        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()\n        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:\n            f.write(MAIN)\n\n        # Make sure the tornado module under test is available to the test\n        # application\n        pythonpath = os.getcwd()\n        if 'PYTHONPATH' in os.environ:\n            pythonpath += os.pathsep + os.environ['PYTHONPATH']\n\n        p = Popen(\n            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,\n            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),\n            universal_newlines=True)\n        out = p.communicate()[0]\n        self.assertEqual(out, 'Starting\\nStarting\\n')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 28,
                            "end_lineno": 48,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "import",
                            "name": "os",
                            "content": "import os",
                            "ast_type_str": "Import",
                            "start_lineno": 2,
                            "end_lineno": 2,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "import",
                            "name": "sys",
                            "content": "import sys",
                            "ast_type_str": "Import",
                            "start_lineno": 5,
                            "end_lineno": 5,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "statement",
                            "name": "",
                            "content": "from tempfile import mkdtemp",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 6,
                            "end_lineno": 6,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "statement",
                            "name": "",
                            "content": "MAIN = \"\"\"\\\nimport os\nimport sys\n\nfrom tornado import autoreload\n\n# This import will fail if path is not set up correctly\nimport testapp\n\nprint('Starting')\nif 'TESTAPP_STARTED' not in os.environ:\n    os.environ['TESTAPP_STARTED'] = '1'\n    sys.stdout.flush()\n    autoreload._reload()\n\"\"\"",
                            "ast_type_str": "Assign",
                            "start_lineno": 11,
                            "end_lineno": 25,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "statement",
                            "name": "",
                            "content": "from tornado.test.util import unittest",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 8,
                            "end_lineno": 8,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "statement",
                            "name": "",
                            "content": "from subprocess import Popen",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 4,
                            "end_lineno": 4,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "import",
                            "name": "subprocess",
                            "content": "import subprocess",
                            "ast_type_str": "Import",
                            "start_lineno": 3,
                            "end_lineno": 3,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "statement",
                            "name": "",
                            "content": "from __future__ import absolute_import, division, print_function",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 1,
                            "end_lineno": 1,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/autoreload_test.py",
                            "type": "method",
                            "name": "AutoreloadTest.test_reload_module",
                            "content": "class AutoreloadTest(unittest.TestCase):\n    def test_reload_module(self):\n        # Create temporary test application\n        path = mkdtemp()\n        os.mkdir(os.path.join(path, 'testapp'))\n        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()\n        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:\n            f.write(MAIN)\n\n        # Make sure the tornado module under test is available to the test\n        # application\n        pythonpath = os.getcwd()\n        if 'PYTHONPATH' in os.environ:\n            pythonpath += os.pathsep + os.environ['PYTHONPATH']\n\n        p = Popen(\n            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,\n            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),\n            universal_newlines=True)\n        out = p.communicate()[0]\n        self.assertEqual(out, 'Starting\\nStarting\\n')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 29,
                            "end_lineno": 48,
                            "parent": {
                                "file_name": "tornado/test/autoreload_test.py",
                                "type": "class",
                                "name": "AutoreloadTest",
                                "content": "class AutoreloadTest(unittest.TestCase):\n    def test_reload_module(self):\n        # Create temporary test application\n        path = mkdtemp()\n        os.mkdir(os.path.join(path, 'testapp'))\n        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()\n        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:\n            f.write(MAIN)\n\n        # Make sure the tornado module under test is available to the test\n        # application\n        pythonpath = os.getcwd()\n        if 'PYTHONPATH' in os.environ:\n            pythonpath += os.pathsep + os.environ['PYTHONPATH']\n\n        p = Popen(\n            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,\n            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),\n            universal_newlines=True)\n        out = p.communicate()[0]\n        self.assertEqual(out, 'Starting\\nStarting\\n')",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 28,
                                "end_lineno": 48,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#!/usr/bin/env python\n\nfrom __future__ import absolute_import, division, print_function\nimport gc\nimport locale  # system locale module, not tornado.locale\nimport logging\nimport operator\nimport textwrap\nimport sys\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httpserver import HTTPServer\nfrom tornado.ioloop import IOLoop\nfrom tornado.netutil import Resolver\nfrom tornado.options import define, options, add_parse_callback\nfrom tornado.test.util import unittest\n\ntry:\n    reduce  # py2\nexcept NameError:\n    from functools import reduce  # py3\n\nTEST_MODULES = [\n    'tornado.httputil.doctests',\n    'tornado.iostream.doctests',\n    'tornado.util.doctests',\n    'tornado.test.asyncio_test',\n    'tornado.test.auth_test',\n    'tornado.test.concurrent_test',\n    'tornado.test.curl_httpclient_test',\n    'tornado.test.escape_test',\n    'tornado.test.gen_test',\n    'tornado.test.http1connection_test',\n    'tornado.test.httpclient_test',\n    'tornado.test.httpserver_test',\n    'tornado.test.httputil_test',\n    'tornado.test.import_test',\n    'tornado.test.ioloop_test',\n    'tornado.test.iostream_test',\n    'tornado.test.locale_test',\n    'tornado.test.locks_test',\n    'tornado.test.netutil_test',\n    'tornado.test.log_test',\n    'tornado.test.options_test',\n    'tornado.test.process_test',\n    'tornado.test.queues_test',\n    'tornado.test.routing_test',\n    'tornado.test.simple_httpclient_test',\n    'tornado.test.stack_context_test',\n    'tornado.test.tcpclient_test',\n    'tornado.test.tcpserver_test',\n    'tornado.test.template_test',\n    'tornado.test.testing_test',\n    'tornado.test.twisted_test',\n    'tornado.test.util_test',\n    'tornado.test.web_test',\n    'tornado.test.websocket_test',\n    'tornado.test.windows_test',\n    'tornado.test.wsgi_test',\n]\n\n\ndef all():\n    return unittest.defaultTestLoader.loadTestsFromNames(TEST_MODULES)\n\n\nclass TornadoTextTestRunner(unittest.TextTestRunner):\n    def run(self, test):\n        result = super(TornadoTextTestRunner, self).run(test)\n        if result.skipped:\n            skip_reasons = set(reason for (test, reason) in result.skipped)\n            self.stream.write(textwrap.fill(\n                \"Some tests were skipped because: %s\" %\n                \", \".join(sorted(skip_reasons))))\n            self.stream.write(\"\\n\")\n        return result\n\n\nclass LogCounter(logging.Filter):\n    \"\"\"Counts the number of WARNING or higher log records.\"\"\"\n    def __init__(self, *args, **kwargs):\n        # Can't use super() because logging.Filter is an old-style class in py26\n        logging.Filter.__init__(self, *args, **kwargs)\n        self.info_count = self.warning_count = self.error_count = 0\n\n    def filter(self, record):\n        if record.levelno >= logging.ERROR:\n            self.error_count += 1\n        elif record.levelno >= logging.WARNING:\n            self.warning_count += 1\n        elif record.levelno >= logging.INFO:\n            self.info_count += 1\n        return True\n\n\ndef main():\n    # The -W command-line option does not work in a virtualenv with\n    # python 3 (as of virtualenv 1.7), so configure warnings\n    # programmatically instead.\n    import warnings\n    # Be strict about most warnings.  This also turns on warnings that are\n    # ignored by default, including DeprecationWarnings and\n    # python 3.2's ResourceWarnings.\n    warnings.filterwarnings(\"error\")\n    # setuptools sometimes gives ImportWarnings about things that are on\n    # sys.path even if they're not being used.\n    warnings.filterwarnings(\"ignore\", category=ImportWarning)\n    # Tornado generally shouldn't use anything deprecated, but some of\n    # our dependencies do (last match wins).\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning)\n    warnings.filterwarnings(\"error\", category=DeprecationWarning,\n                            module=r\"tornado\\..*\")\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning)\n    warnings.filterwarnings(\"error\", category=PendingDeprecationWarning,\n                            module=r\"tornado\\..*\")\n    # The unittest module is aggressive about deprecating redundant methods,\n    # leaving some without non-deprecated spellings that work on both\n    # 2.7 and 3.2\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning,\n                            message=\"Please use assert.* instead\")\n    # unittest2 0.6 on py26 reports these as PendingDeprecationWarnings\n    # instead of DeprecationWarnings.\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning,\n                            message=\"Please use assert.* instead\")\n    # Twisted 15.0.0 triggers some warnings on py3 with -bb.\n    warnings.filterwarnings(\"ignore\", category=BytesWarning,\n                            module=r\"twisted\\..*\")\n    # The __aiter__ protocol changed in python 3.5.2.\n    # Silence the warning until we can drop 3.5.[01].\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning,\n                            message=\".*legacy __aiter__ protocol\")\n    # 3.5.2's PendingDeprecationWarning became a DeprecationWarning in 3.6.\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning,\n                            message=\".*legacy __aiter__ protocol\")\n\n    logging.getLogger(\"tornado.access\").setLevel(logging.CRITICAL)\n\n    define('httpclient', type=str, default=None,\n           callback=lambda s: AsyncHTTPClient.configure(\n               s, defaults=dict(allow_ipv6=False)))\n    define('httpserver', type=str, default=None,\n           callback=HTTPServer.configure)\n    define('ioloop', type=str, default=None)\n    define('ioloop_time_monotonic', default=False)\n    define('resolver', type=str, default=None,\n           callback=Resolver.configure)\n    define('debug_gc', type=str, multiple=True,\n           help=\"A comma-separated list of gc module debug constants, \"\n           \"e.g. DEBUG_STATS or DEBUG_COLLECTABLE,DEBUG_OBJECTS\",\n           callback=lambda values: gc.set_debug(\n               reduce(operator.or_, (getattr(gc, v) for v in values))))\n    define('locale', type=str, default=None,\n           callback=lambda x: locale.setlocale(locale.LC_ALL, x))\n\n    def configure_ioloop():\n        kwargs = {}\n        if options.ioloop_time_monotonic:\n            from tornado.platform.auto import monotonic_time\n            if monotonic_time is None:\n                raise RuntimeError(\"monotonic clock not found\")\n            kwargs['time_func'] = monotonic_time\n        if options.ioloop or kwargs:\n            IOLoop.configure(options.ioloop, **kwargs)\n    add_parse_callback(configure_ioloop)\n\n    log_counter = LogCounter()\n    add_parse_callback(\n        lambda: logging.getLogger().handlers[0].addFilter(log_counter))\n\n    import tornado.testing\n    kwargs = {}\n    if sys.version_info >= (3, 2):\n        # HACK:  unittest.main will make its own changes to the warning\n        # configuration, which may conflict with the settings above\n        # or command-line flags like -bb.  Passing warnings=False\n        # suppresses this behavior, although this looks like an implementation\n        # detail.  http://bugs.python.org/issue15626\n        kwargs['warnings'] = False\n    kwargs['testRunner'] = TornadoTextTestRunner\n    try:\n        tornado.testing.main(**kwargs)\n    finally:\n        # The tests should run clean; consider it a failure if they\n        # logged anything at info level or above (except for the one\n        # allowed info message \"PASS\")\n        if (log_counter.info_count > 1 or\n            log_counter.warning_count > 0 or\n            log_counter.error_count > 0):\n            logging.error(\"logged %d infos, %d warnings, and %d errors\",\n                          log_counter.info_count, log_counter.warning_count,\n                          log_counter.error_count)\n            sys.exit(1)\n\n\nif __name__ == '__main__':\n    main()\n",
            "new_file_content": "#!/usr/bin/env python\n\nfrom __future__ import absolute_import, division, print_function\nimport gc\nimport locale  # system locale module, not tornado.locale\nimport logging\nimport operator\nimport textwrap\nimport sys\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httpserver import HTTPServer\nfrom tornado.ioloop import IOLoop\nfrom tornado.netutil import Resolver\nfrom tornado.options import define, options, add_parse_callback\nfrom tornado.test.util import unittest\n\ntry:\n    reduce  # py2\nexcept NameError:\n    from functools import reduce  # py3\n\nTEST_MODULES = [\n    'tornado.httputil.doctests',\n    'tornado.iostream.doctests',\n    'tornado.util.doctests',\n    'tornado.test.asyncio_test',\n    'tornado.test.auth_test',\n    'tornado.test.autoreload_test',\n    'tornado.test.concurrent_test',\n    'tornado.test.curl_httpclient_test',\n    'tornado.test.escape_test',\n    'tornado.test.gen_test',\n    'tornado.test.http1connection_test',\n    'tornado.test.httpclient_test',\n    'tornado.test.httpserver_test',\n    'tornado.test.httputil_test',\n    'tornado.test.import_test',\n    'tornado.test.ioloop_test',\n    'tornado.test.iostream_test',\n    'tornado.test.locale_test',\n    'tornado.test.locks_test',\n    'tornado.test.netutil_test',\n    'tornado.test.log_test',\n    'tornado.test.options_test',\n    'tornado.test.process_test',\n    'tornado.test.queues_test',\n    'tornado.test.routing_test',\n    'tornado.test.simple_httpclient_test',\n    'tornado.test.stack_context_test',\n    'tornado.test.tcpclient_test',\n    'tornado.test.tcpserver_test',\n    'tornado.test.template_test',\n    'tornado.test.testing_test',\n    'tornado.test.twisted_test',\n    'tornado.test.util_test',\n    'tornado.test.web_test',\n    'tornado.test.websocket_test',\n    'tornado.test.windows_test',\n    'tornado.test.wsgi_test',\n]\n\n\ndef all():\n    return unittest.defaultTestLoader.loadTestsFromNames(TEST_MODULES)\n\n\nclass TornadoTextTestRunner(unittest.TextTestRunner):\n    def run(self, test):\n        result = super(TornadoTextTestRunner, self).run(test)\n        if result.skipped:\n            skip_reasons = set(reason for (test, reason) in result.skipped)\n            self.stream.write(textwrap.fill(\n                \"Some tests were skipped because: %s\" %\n                \", \".join(sorted(skip_reasons))))\n            self.stream.write(\"\\n\")\n        return result\n\n\nclass LogCounter(logging.Filter):\n    \"\"\"Counts the number of WARNING or higher log records.\"\"\"\n    def __init__(self, *args, **kwargs):\n        # Can't use super() because logging.Filter is an old-style class in py26\n        logging.Filter.__init__(self, *args, **kwargs)\n        self.info_count = self.warning_count = self.error_count = 0\n\n    def filter(self, record):\n        if record.levelno >= logging.ERROR:\n            self.error_count += 1\n        elif record.levelno >= logging.WARNING:\n            self.warning_count += 1\n        elif record.levelno >= logging.INFO:\n            self.info_count += 1\n        return True\n\n\ndef main():\n    # The -W command-line option does not work in a virtualenv with\n    # python 3 (as of virtualenv 1.7), so configure warnings\n    # programmatically instead.\n    import warnings\n    # Be strict about most warnings.  This also turns on warnings that are\n    # ignored by default, including DeprecationWarnings and\n    # python 3.2's ResourceWarnings.\n    warnings.filterwarnings(\"error\")\n    # setuptools sometimes gives ImportWarnings about things that are on\n    # sys.path even if they're not being used.\n    warnings.filterwarnings(\"ignore\", category=ImportWarning)\n    # Tornado generally shouldn't use anything deprecated, but some of\n    # our dependencies do (last match wins).\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning)\n    warnings.filterwarnings(\"error\", category=DeprecationWarning,\n                            module=r\"tornado\\..*\")\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning)\n    warnings.filterwarnings(\"error\", category=PendingDeprecationWarning,\n                            module=r\"tornado\\..*\")\n    # The unittest module is aggressive about deprecating redundant methods,\n    # leaving some without non-deprecated spellings that work on both\n    # 2.7 and 3.2\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning,\n                            message=\"Please use assert.* instead\")\n    # unittest2 0.6 on py26 reports these as PendingDeprecationWarnings\n    # instead of DeprecationWarnings.\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning,\n                            message=\"Please use assert.* instead\")\n    # Twisted 15.0.0 triggers some warnings on py3 with -bb.\n    warnings.filterwarnings(\"ignore\", category=BytesWarning,\n                            module=r\"twisted\\..*\")\n    # The __aiter__ protocol changed in python 3.5.2.\n    # Silence the warning until we can drop 3.5.[01].\n    warnings.filterwarnings(\"ignore\", category=PendingDeprecationWarning,\n                            message=\".*legacy __aiter__ protocol\")\n    # 3.5.2's PendingDeprecationWarning became a DeprecationWarning in 3.6.\n    warnings.filterwarnings(\"ignore\", category=DeprecationWarning,\n                            message=\".*legacy __aiter__ protocol\")\n\n    logging.getLogger(\"tornado.access\").setLevel(logging.CRITICAL)\n\n    define('httpclient', type=str, default=None,\n           callback=lambda s: AsyncHTTPClient.configure(\n               s, defaults=dict(allow_ipv6=False)))\n    define('httpserver', type=str, default=None,\n           callback=HTTPServer.configure)\n    define('ioloop', type=str, default=None)\n    define('ioloop_time_monotonic', default=False)\n    define('resolver', type=str, default=None,\n           callback=Resolver.configure)\n    define('debug_gc', type=str, multiple=True,\n           help=\"A comma-separated list of gc module debug constants, \"\n           \"e.g. DEBUG_STATS or DEBUG_COLLECTABLE,DEBUG_OBJECTS\",\n           callback=lambda values: gc.set_debug(\n               reduce(operator.or_, (getattr(gc, v) for v in values))))\n    define('locale', type=str, default=None,\n           callback=lambda x: locale.setlocale(locale.LC_ALL, x))\n\n    def configure_ioloop():\n        kwargs = {}\n        if options.ioloop_time_monotonic:\n            from tornado.platform.auto import monotonic_time\n            if monotonic_time is None:\n                raise RuntimeError(\"monotonic clock not found\")\n            kwargs['time_func'] = monotonic_time\n        if options.ioloop or kwargs:\n            IOLoop.configure(options.ioloop, **kwargs)\n    add_parse_callback(configure_ioloop)\n\n    log_counter = LogCounter()\n    add_parse_callback(\n        lambda: logging.getLogger().handlers[0].addFilter(log_counter))\n\n    import tornado.testing\n    kwargs = {}\n    if sys.version_info >= (3, 2):\n        # HACK:  unittest.main will make its own changes to the warning\n        # configuration, which may conflict with the settings above\n        # or command-line flags like -bb.  Passing warnings=False\n        # suppresses this behavior, although this looks like an implementation\n        # detail.  http://bugs.python.org/issue15626\n        kwargs['warnings'] = False\n    kwargs['testRunner'] = TornadoTextTestRunner\n    try:\n        tornado.testing.main(**kwargs)\n    finally:\n        # The tests should run clean; consider it a failure if they\n        # logged anything at info level or above (except for the one\n        # allowed info message \"PASS\")\n        if (log_counter.info_count > 1 or\n            log_counter.warning_count > 0 or\n            log_counter.error_count > 0):\n            logging.error(\"logged %d infos, %d warnings, and %d errors\",\n                          log_counter.info_count, log_counter.warning_count,\n                          log_counter.error_count)\n            sys.exit(1)\n\n\nif __name__ == '__main__':\n    main()\n",
            "header": {
                "file": {
                    "path": "tornado/test/runtests.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "dc702eda",
                "new_commit_hash": "8c1b6a54",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/runtests.py"
            },
            "plus_file": {
                "path": "b/tornado/test/runtests.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 25,
                            "length": 6
                        },
                        "new_range": {
                            "start": 25,
                            "length": 7
                        },
                        "section": "TEST_MODULES = ["
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    'tornado.util.doctests',",
                                "type": "context"
                            },
                            {
                                "content": "    'tornado.test.asyncio_test',",
                                "type": "context"
                            },
                            {
                                "content": "    'tornado.test.auth_test',",
                                "type": "context"
                            },
                            {
                                "content": "    'tornado.test.autoreload_test',",
                                "type": "added"
                            },
                            {
                                "content": "    'tornado.test.concurrent_test',",
                                "type": "context"
                            },
                            {
                                "content": "    'tornado.test.curl_httpclient_test',",
                                "type": "context"
                            },
                            {
                                "content": "    'tornado.test.escape_test',",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/runtests.py",
                            "type": "statement",
                            "name": "",
                            "content": "TEST_MODULES = [\n    'tornado.httputil.doctests',\n    'tornado.iostream.doctests',\n    'tornado.util.doctests',\n    'tornado.test.asyncio_test',\n    'tornado.test.auth_test',\n    'tornado.test.autoreload_test',\n    'tornado.test.concurrent_test',\n    'tornado.test.curl_httpclient_test',\n    'tornado.test.escape_test',\n    'tornado.test.gen_test',\n    'tornado.test.http1connection_test',\n    'tornado.test.httpclient_test',\n    'tornado.test.httpserver_test',\n    'tornado.test.httputil_test',\n    'tornado.test.import_test',\n    'tornado.test.ioloop_test',\n    'tornado.test.iostream_test',\n    'tornado.test.locale_test',\n    'tornado.test.locks_test',\n    'tornado.test.netutil_test',\n    'tornado.test.log_test',\n    'tornado.test.options_test',\n    'tornado.test.process_test',\n    'tornado.test.queues_test',\n    'tornado.test.routing_test',\n    'tornado.test.simple_httpclient_test',\n    'tornado.test.stack_context_test',\n    'tornado.test.tcpclient_test',\n    'tornado.test.tcpserver_test',\n    'tornado.test.template_test',\n    'tornado.test.testing_test',\n    'tornado.test.twisted_test',\n    'tornado.test.util_test',\n    'tornado.test.web_test',\n    'tornado.test.websocket_test',\n    'tornado.test.windows_test',\n    'tornado.test.wsgi_test',\n]",
                            "ast_type_str": "Assign",
                            "start_lineno": 22,
                            "end_lineno": 60,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "52bec504f714785a3c30e76f6925fd65d2298848^",
    "new_commit_hash": "52bec504f714785a3c30e76f6925fd65d2298848",
    "commit_message": "Merge pull request #2081 from noyainrain/fix-autoreload-module\n\nFix module autoreload for __main__ with relative imports",
    "commit_date": "2017-06-17T22:24:50-04:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "52bec504f714785a3c30e76f6925fd65d2298848",
    "test_file_codes": [
        "from __future__ import absolute_import, division, print_function\nimport os\nimport subprocess\nfrom subprocess import Popen\nimport sys\nfrom tempfile import mkdtemp\n\nfrom tornado.test.util import unittest\n\n\nMAIN = \"\"\"\\\nimport os\nimport sys\n\nfrom tornado import autoreload\n\n# This import will fail if path is not set up correctly\nimport testapp\n\nprint('Starting')\nif 'TESTAPP_STARTED' not in os.environ:\n    os.environ['TESTAPP_STARTED'] = '1'\n    sys.stdout.flush()\n    autoreload._reload()\n\"\"\"\n\n\nclass AutoreloadTest(unittest.TestCase):\n    def test_reload_module(self):\n        # Create temporary test application\n        path = mkdtemp()\n        os.mkdir(os.path.join(path, 'testapp'))\n        open(os.path.join(path, 'testapp/__init__.py'), 'w').close()\n        with open(os.path.join(path, 'testapp/__main__.py'), 'w') as f:\n            f.write(MAIN)\n\n        # Make sure the tornado module under test is available to the test\n        # application\n        pythonpath = os.getcwd()\n        if 'PYTHONPATH' in os.environ:\n            pythonpath += os.pathsep + os.environ['PYTHONPATH']\n\n        p = Popen(\n            [sys.executable, '-m', 'testapp'], stdout=subprocess.PIPE,\n            cwd=path, env=dict(os.environ, PYTHONPATH=pythonpath),\n            universal_newlines=True)\n        out = p.communicate()[0]\n        self.assertEqual(out, 'Starting\\nStarting\\n')\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n    def tearDown(self):\n        # Reset signal handlers\n        from twisted.internet import reactor\n\n        reactor.removeAll()\n        reactor.stop()\n        super().tearDown()\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\".\", pattern=\"test_*.py\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "tornado_unittest_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 818ms\nPrepared 1 package in 1.02s\nInstalled 1 package in 1ms\n + tornado==5.0.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_52bec504f714785a3c30e76f6925fd65d2298848)\nResolved 29 packages in 11ms\nInstalled 29 packages in 152ms\n + attrs==24.3.0\n + automat==24.8.1\n + cachetools==5.5.0\n + cffi==1.17.1\n + chardet==5.2.0\n + colorama==0.4.6\n + constantly==23.10.4\n + distlib==0.3.9\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + hyperlink==21.0.0\n + idna==3.10\n + incremental==24.7.2\n + iniconfig==2.0.0\n + packaging==24.2\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pycares==4.5.0\n + pycparser==2.22\n + pycurl==7.45.4\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + setuptools==75.6.0\n + tomli==2.2.1\n + tox==4.23.2\n + twisted==24.11.0\n + typing-extensions==4.12.2\n + virtualenv==20.28.0\n + zope-interface==7.2\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_52bec504f714785a3c30e76f6925fd65d2298848\n.\ncollected 1 items\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::AutoreloadTest::test_reload_module\n=================== 1 passed in 0.22s ===================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_52bec504f714785a3c30e76f6925fd65d2298848\n.\ncollected 1 items\n\n=================================== FAILURES ===================================\n__________ AutoreloadTest.test_reload_module __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_52bec504f714785a3c30e76f6925fd65d2298848/r2e_tests/test_1.py\", line 48, in test_reload_module\n    self.assertEqual(out, 'Starting\\nStarting\\n')\nAssertionError: 'Starting\\n' != 'Starting\\nStarting\\n'\n  Starting\n+ Starting\n\n\n==================== short test summary info ====================\nFAILED r2e_tests.test_1::AutoreloadTest::test_reload_module\n=================== 1 failed in 0.19s ===================\n",
    "old_commit_res_stderr": "Traceback (most recent call last):\n  File \"/tmp/tmpnatixr0w/testapp/__main__.py\", line 7, in <module>\n    import testapp\nModuleNotFoundError: No module named 'testapp'\n"
}
tornado/autoreload.py tornado/test/autoreload_test.py tornado/test/runtests.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Autoreload Fails to Reload `__main__` Module with Relative Imports

**Description:**
When running a Tornado application using `autoreload` as the `__main__` module with relative imports, the autoreload mechanism does not properly reload the module. This results in the application not restarting as expected upon file changes.

**Reproduce the Issue:**
```python
# main.py
import os
import sys
from tornado import autoreload

# This import relies on relative imports
import myapp

print('Starting')
if 'MYAPP_STARTED' not in os.environ:
    os.environ['MYAPP_STARTED'] = '1'
    sys.stdout.flush()
    autoreload._reload()
```

**Expected Behavior:**
Upon running the script, "Starting" should be printed twice. The first print occurs initially, and the second print should happen after `autoreload` triggers a reload of the `__main__` module.

**Actual Behavior:**
Only "Starting" is printed once, indicating that the module was not reloaded as expected.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/autoreload.py
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Automatically restart the server when a source file is modified.

Most applications should not access this module directly.  Instead,
pass the keyword argument ``autoreload=True`` to the
`tornado.web.Application` constructor (or ``debug=True``, which
enables this setting and several others).  This will enable autoreload
mode as well as checking for changes to templates and static
resources.  Note that restarting is a destructive operation and any
requests in progress will be aborted when the process restarts.  (If
you want to disable autoreload while using other debug-mode features,
pass both ``debug=True`` and ``autoreload=False``).

This module can also be used as a command-line wrapper around scripts
such as unit test runners.  See the `main` method for details.

The command-line wrapper and Application debug modes can be used together.
This combination is encouraged as the wrapper catches syntax errors and
other import-time failures, while debug mode catches changes once
the server has started.

This module depends on `.IOLoop`, so it will not work in WSGI applications
and Google App Engine.  It also will not work correctly when `.HTTPServer`'s
multi-process mode is used.

Reloading loses any Python interpreter command-line arguments (e.g. ``-u``)
because it re-executes Python using ``sys.executable`` and ``sys.argv``.
Additionally, modifying these variables will cause reloading to behave
incorrectly.

"""

from __future__ import absolute_import, division, print_function

import os
import sys

# sys.path handling
# -----------------
#
# If a module is run with "python -m", the current directory (i.e. "")
# is automatically prepended to sys.path, but not if it is run as
# "path/to/file.py".  The processing for "-m" rewrites the former to
# the latter, so subsequent executions won't have the same path as the
# original.
#
# Conversely, when run as path/to/file.py, the directory containing
# file.py gets added to the path, which can cause confusion as imports
# may become relative in spite of the future import.
#
# We address the former problem by setting the $PYTHONPATH environment
# variable before re-execution so the new process will see the correct
# path.  We attempt to address the latter problem when tornado.autoreload
# is run as __main__, although we can't fix the general case because
# we cannot reliably reconstruct the original command line
# (http://bugs.python.org/issue14208).

if __name__ == "__main__":
    # This sys.path manipulation must come before our imports (as much
    # as possible - if we introduced a tornado.sys or tornado.os
    # module we'd be in trouble), or else our imports would become
    # relative again despite the future import.
    #
    # There is a separate __main__ block at the end of the file to call main().
    if sys.path[0] == os.path.dirname(__file__):
        del sys.path[0]

import functools
import logging
import os
import pkgutil  # type: ignore
import sys
import traceback
import types
import subprocess
import weakref

from tornado import ioloop
from tornado.log import gen_log
from tornado import process
from tornado.util import exec_in

try:
    import signal
except ImportError:
    signal = None

# os.execv is broken on Windows and can't properly parse command line
# arguments and executable name if they contain whitespaces. subprocess
# fixes that behavior.
_has_execv = sys.platform != 'win32'

_watched_files = set()
_reload_hooks = []
_reload_attempted = False
_io_loops = weakref.WeakKeyDictionary()  # type: ignore


def start(check_time=500):
    """Begins watching source files for changes.

    .. versionchanged:: 5.0
       The ``io_loop`` argument (deprecated since version 4.1) has been removed.
    """
    io_loop = ioloop.IOLoop.current()
    if io_loop in _io_loops:
        return
    _io_loops[io_loop] = True
    if len(_io_loops) > 1:
        gen_log.warning("tornado.autoreload started more than once in the same process")
    modify_times = {}
    callback = functools.partial(_reload_on_update, modify_times)
    scheduler = ioloop.PeriodicCallback(callback, check_time)
    scheduler.start()


def wait():
    """Wait for a watched file to change, then restart the process.

    Intended to be used at the end of scripts like unit test runners,
    to run the tests again after any source file changes (but see also
    the command-line interface in `main`)
    """
    io_loop = ioloop.IOLoop()
    start(io_loop)
    io_loop.start()


def watch(filename):
    """Add a file to the watch list.

    All imported modules are watched by default.
    """
    _watched_files.add(filename)


def add_reload_hook(fn):
    """Add a function to be called before reloading the process.

    Note that for open file and socket handles it is generally
    preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or
    ``tornado.platform.auto.set_close_exec``) instead
    of using a reload hook to close them.
    """
    _reload_hooks.append(fn)


def _reload_on_update(modify_times):
    if _reload_attempted:
        # We already tried to reload and it didn't work, so don't try again.
        return
    if process.task_id() is not None:
        # We're in a child process created by fork_processes.  If child
        # processes restarted themselves, they'd all restart and then
        # all call fork_processes again.
        return
    for module in list(sys.modules.values()):
        # Some modules play games with sys.modules (e.g. email/__init__.py
        # in the standard library), and occasionally this can cause strange
        # failures in getattr.  Just ignore anything that's not an ordinary
        # module.
        if not isinstance(module, types.ModuleType):
            continue
        path = getattr(module, "__file__", None)
        if not path:
            continue
        if path.endswith(".pyc") or path.endswith(".pyo"):
            path = path[:-1]
        _check_file(modify_times, path)
    for path in _watched_files:
        _check_file(modify_times, path)


def _check_file(modify_times, path):
    try:
        modified = os.stat(path).st_mtime
    except Exception:
        return
    if path not in modify_times:
        modify_times[path] = modified
        return
    if modify_times[path] != modified:
        gen_log.info("%s modified; restarting server", path)
        _reload()


def _reload():
    global _reload_attempted
    _reload_attempted = True
    for fn in _reload_hooks:
        fn()
    if hasattr(signal, "setitimer"):
        # Clear the alarm signal set by
        # ioloop.set_blocking_log_threshold so it doesn't fire
        # after the exec.
        signal.setitimer(signal.ITIMER_REAL, 0, 0)
    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty
    # string, we were (probably) invoked with -m and the effective path
    # is about to change on re-exec.  Add the current directory to $PYTHONPATH
    # to ensure that the new process sees the same path we did.
    path_prefix = '.' + os.pathsep
    if (sys.path[0] == '' and
            not os.environ.get("PYTHONPATH", "").startswith(path_prefix)):
        os.environ["PYTHONPATH"] = (path_prefix +
                                    os.environ.get("PYTHONPATH", ""))
    if not _has_execv:
        subprocess.Popen([sys.executable] + sys.argv)
        sys.exit(0)
    else:
        try:
            os.execv(sys.executable, [sys.executable] + sys.argv)
        except OSError:
            # Mac OS X versions prior to 10.6 do not support execv in
            # a process that contains multiple threads.  Instead of
            # re-executing in the current process, start a new one
            # and cause the current process to exit.  This isn't
            # ideal since the new process is detached from the parent
            # terminal and thus cannot easily be killed with ctrl-C,
            # but it's better than not being able to autoreload at
            # all.
            # Unfortunately the errno returned in this case does not
            # appear to be consistent, so we can't easily check for
            # this error specifically.
            os.spawnv(os.P_NOWAIT, sys.executable,
                      [sys.executable] + sys.argv)
            # At this point the IOLoop has been closed and finally
            # blocks will experience errors if we allow the stack to
            # unwind, so just exit uncleanly.
            os._exit(0)


_USAGE = """\
Usage:
  python -m tornado.autoreload -m module.to.run [args...]
  python -m tornado.autoreload path/to/script.py [args...]
"""


def main():
    """Command-line wrapper to re-run a script whenever its source changes.

    Scripts may be specified by filename or module name::

        python -m tornado.autoreload -m tornado.test.runtests
        python -m tornado.autoreload tornado/test/runtests.py

    Running a script with this wrapper is similar to calling
    `tornado.autoreload.wait` at the end of the script, but this wrapper
    can catch import-time problems like syntax errors that would otherwise
    prevent the script from reaching its call to `wait`.
    """
    original_argv = sys.argv
    sys.argv = sys.argv[:]
    if len(sys.argv) >= 3 and sys.argv[1] == "-m":
        mode = "module"
        module = sys.argv[2]
        del sys.argv[1:3]
    elif len(sys.argv) >= 2:
        mode = "script"
        script = sys.argv[1]
        sys.argv = sys.argv[1:]
    else:
        print(_USAGE, file=sys.stderr)
        sys.exit(1)

    try:
        if mode == "module":
            import runpy
            runpy.run_module(module, run_name="__main__", alter_sys=True)
        elif mode == "script":
            with open(script) 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__ = script
                # If __package__ is defined, imports may be incorrectly
                # interpreted as relative to this module.
                global __package__
                del __package__
                exec_in(f.read(), globals(), globals())
    except SystemExit as e:
        logging.basicConfig()
        gen_log.info("Script exited with status %s", e.code)
    except Exception as e:
        logging.basicConfig()
        gen_log.warning("Script exited with uncaught exception", exc_info=True)
        # If an exception occurred at import time, the file with the error
        # never made it into sys.modules and so we won't know to watch it.
        # Just to make sure we've covered everything, walk the stack trace
        # from the exception and watch every file.
        for (filename, lineno, name, line) in traceback.extract_tb(sys.exc_info()[2]):
            watch(filename)
        if isinstance(e, SyntaxError):
            # SyntaxErrors are special:  their innermost stack frame is fake
            # so extract_tb won't see it and we have to get the filename
            # from the exception object.
            watch(e.filename)
    else:
        logging.basicConfig()
        gen_log.info("Script exited normally")
    # restore sys.argv so subsequent executions will include autoreload
    sys.argv = original_argv

    if mode == 'module':
        # runpy did a fake import of the module as __main__, but now it's
        # no longer in sys.modules.  Figure out where it is and watch it.
        loader = pkgutil.get_loader(module)
        if loader is not None:
            watch(loader.get_filename())

    wait()


if __name__ == "__main__":
    # See also the other __main__ block at the top of the file, which modifies
    # sys.path before our imports
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** Autoreload Fails to Reload `__main__` Module with Relative Imports

**Description:**
When running a Tornado application using `autoreload` as the `__main__` module with relative imports, the autoreload mechanism does not properly reload the module. This results in the application not restarting as expected upon file changes.

**Reproduce the Issue:**
```python
# main.py
import os
import sys
from tornado import autoreload

# This import relies on relative imports
import myapp

print('Starting')
if 'MYAPP_STARTED' not in os.environ:
    os.environ['MYAPP_STARTED'] = '1'
    sys.stdout.flush()
    autoreload._reload()
```

**Expected Behavior:**
Upon running the script, "Starting" should be printed twice. The first print occurs initially, and the second print should happen after `autoreload` triggers a reload of the `__main__` module.

**Actual Behavior:**
Only "Starting" is printed once, indicating that the module was not reloaded as expected.

[/ISSUE]
{
    "AutoreloadTest.test_reload_module": "PASSED"
}
diff --git a/tornado/autoreload.py b/tornado/autoreload.py
index 24deb79d..da1b100d 100644
--- a/tornado/autoreload.py
+++ b/tornado/autoreload.py
@@ -63,12 +63,11 @@ import sys
 # file.py gets added to the path, which can cause confusion as imports
 # may become relative in spite of the future import.
 #
-# We address the former problem by setting the $PYTHONPATH environment
-# variable before re-execution so the new process will see the correct
-# path.  We attempt to address the latter problem when tornado.autoreload
-# is run as __main__, although we can't fix the general case because
-# we cannot reliably reconstruct the original command line
-# (http://bugs.python.org/issue14208).
+# We address the former problem by reconstructing the original command
+# line (Python >= 3.4) or by setting the $PYTHONPATH environment
+# variable (Python < 3.4) before re-execution so the new process will
+# see the correct path.  We attempt to address the latter problem when
+# tornado.autoreload is run as __main__.
 
 if __name__ == "__main__":
     # This sys.path manipulation must come before our imports (as much
@@ -209,21 +208,29 @@ def _reload():
         # ioloop.set_blocking_log_threshold so it doesn't fire
         # after the exec.
         signal.setitimer(signal.ITIMER_REAL, 0, 0)
-    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty
-    # string, we were (probably) invoked with -m and the effective path
-    # is about to change on re-exec.  Add the current directory to $PYTHONPATH
-    # to ensure that the new process sees the same path we did.
-    path_prefix = '.' + os.pathsep
-    if (sys.path[0] == '' and
-            not os.environ.get("PYTHONPATH", "").startswith(path_prefix)):
-        os.environ["PYTHONPATH"] = (path_prefix +
-                                    os.environ.get("PYTHONPATH", ""))
+    # sys.path fixes: see comments at top of file.  If __main__.__spec__
+    # exists, we were invoked with -m and the effective path is about to
+    # change on re-exec.  Reconstruct the original command line to
+    # ensure that the new process sees the same path we did.  If
+    # __spec__ is not available (Python < 3.4), check instead if
+    # sys.path[0] is an empty string and add the current directory to
+    # $PYTHONPATH.
+    spec = getattr(sys.modules['__main__'], '__spec__', None)
+    if spec:
+        argv = ['-m', spec.name] + sys.argv[1:]
+    else:
+        argv = sys.argv
+        path_prefix = '.' + os.pathsep
+        if (sys.path[0] == '' and
+                not os.environ.get("PYTHONPATH", "").startswith(path_prefix)):
+            os.environ["PYTHONPATH"] = (path_prefix +
+                                        os.environ.get("PYTHONPATH", ""))
     if not _has_execv:
-        subprocess.Popen([sys.executable] + sys.argv)
+        subprocess.Popen([sys.executable] + argv)
         sys.exit(0)
     else:
         try:
-            os.execv(sys.executable, [sys.executable] + sys.argv)
+            os.execv(sys.executable, [sys.executable] + argv)
         except OSError:
             # Mac OS X versions prior to 10.6 do not support execv in
             # a process that contains multiple threads.  Instead of
@@ -236,8 +243,7 @@ def _reload():
             # Unfortunately the errno returned in this case does not
             # appear to be consistent, so we can't easily check for
             # this error specifically.
-            os.spawnv(os.P_NOWAIT, sys.executable,
-                      [sys.executable] + sys.argv)
+            os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable] + argv)
             # At this point the IOLoop has been closed and finally
             # blocks will experience errors if we allow the stack to
             # unwind, so just exit uncleanly.

{"tornado/autoreload.py": "#!/usr/bin/env python\n#\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Automatically restart the server when a source file is modified.\n\nMost applications should not access this module directly.  Instead,\npass the keyword argument ``autoreload=True`` to the\n`tornado.web.Application` constructor (or ``debug=True``, which\nenables this setting and several others).  This will enable autoreload\nmode as well as checking for changes to templates and static\nresources.  Note that restarting is a destructive operation and any\nrequests in progress will be aborted when the process restarts.  (If\nyou want to disable autoreload while using other debug-mode features,\npass both ``debug=True`` and ``autoreload=False``).\n\nThis module can also be used as a command-line wrapper around scripts\nsuch as unit test runners.  See the `main` method for details.\n\nThe command-line wrapper and Application debug modes can be used together.\nThis combination is encouraged as the wrapper catches syntax errors and\nother import-time failures, while debug mode catches changes once\nthe server has started.\n\nThis module depends on `.IOLoop`, so it will not work in WSGI applications\nand Google App Engine.  It also will not work correctly when `.HTTPServer`'s\nmulti-process mode is used.\n\nReloading loses any Python interpreter command-line arguments (e.g. ``-u``)\nbecause it re-executes Python using ``sys.executable`` and ``sys.argv``.\nAdditionally, modifying these variables will cause reloading to behave\nincorrectly.\n\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function\n\nimport os\nimport sys\n\n# sys.path handling\n# -----------------\n#\n# If a module is run with \"python -m\", the current directory (i.e. \"\")\n# is automatically prepended to sys.path, but not if it is run as\n# \"path/to/file.py\".  The processing for \"-m\" rewrites the former to\n# the latter, so subsequent executions won't have the same path as the\n# original.\n#\n# Conversely, when run as path/to/file.py, the directory containing\n# file.py gets added to the path, which can cause confusion as imports\n# may become relative in spite of the future import.\n#\n# We address the former problem by setting the $PYTHONPATH environment\n# variable before re-execution so the new process will see the correct\n# path.  We attempt to address the latter problem when tornado.autoreload\n# is run as __main__, although we can't fix the general case because\n# we cannot reliably reconstruct the original command line\n# (http://bugs.python.org/issue14208).\n\nif __name__ == \"__main__\":\n    # This sys.path manipulation must come before our imports (as much\n    # as possible - if we introduced a tornado.sys or tornado.os\n    # module we'd be in trouble), or else our imports would become\n    # relative again despite the future import.\n    #\n    # There is a separate __main__ block at the end of the file to call main().\n    if sys.path[0] == os.path.dirname(__file__):\n        del sys.path[0]\n\nimport functools\nimport logging\nimport os\nimport pkgutil  # type: ignore\nimport sys\nimport traceback\nimport types\nimport subprocess\nimport weakref\n\nfrom tornado import ioloop\nfrom tornado.log import gen_log\nfrom tornado import process\nfrom tornado.util import exec_in\n\ntry:\n    import signal\nexcept ImportError:\n    signal = None\n\n# os.execv is broken on Windows and can't properly parse command line\n# arguments and executable name if they contain whitespaces. subprocess\n# fixes that behavior.\n_has_execv = sys.platform != 'win32'\n\n_watched_files = set()\n_reload_hooks = []\n_reload_attempted = False\n_io_loops = weakref.WeakKeyDictionary()  # type: ignore\n\n\ndef start(check_time=500):\n    \"\"\"Begins watching source files for changes.\n\n    .. versionchanged:: 5.0\n       The ``io_loop`` argument (deprecated since version 4.1) has been removed.\n    \"\"\"\n    io_loop = ioloop.IOLoop.current()\n    if io_loop in _io_loops:\n        return\n    _io_loops[io_loop] = True\n    if len(_io_loops) > 1:\n        gen_log.warning(\"tornado.autoreload started more than once in the same process\")\n    modify_times = {}\n    callback = functools.partial(_reload_on_update, modify_times)\n    scheduler = ioloop.PeriodicCallback(callback, check_time)\n    scheduler.start()\n\n\ndef wait():\n    \"\"\"Wait for a watched file to change, then restart the process.\n\n    Intended to be used at the end of scripts like unit test runners,\n    to run the tests again after any source file changes (but see also\n    the command-line interface in `main`)\n    \"\"\"\n    io_loop = ioloop.IOLoop()\n    start(io_loop)\n    io_loop.start()\n\n\ndef watch(filename):\n    \"\"\"Add a file to the watch list.\n\n    All imported modules are watched by default.\n    \"\"\"\n    _watched_files.add(filename)\n\n\ndef add_reload_hook(fn):\n    \"\"\"Add a function to be called before reloading the process.\n\n    Note that for open file and socket handles it is generally\n    preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or\n    ``tornado.platform.auto.set_close_exec``) instead\n    of using a reload hook to close them.\n    \"\"\"\n    _reload_hooks.append(fn)\n\n\ndef _reload_on_update(modify_times):\n    if _reload_attempted:\n        # We already tried to reload and it didn't work, so don't try again.\n        return\n    if process.task_id() is not None:\n        # We're in a child process created by fork_processes.  If child\n        # processes restarted themselves, they'd all restart and then\n        # all call fork_processes again.\n        return\n    for module in list(sys.modules.values()):\n        # Some modules play games with sys.modules (e.g. email/__init__.py\n        # in the standard library), and occasionally this can cause strange\n        # failures in getattr.  Just ignore anything that's not an ordinary\n        # module.\n        if not isinstance(module, types.ModuleType):\n            continue\n        path = getattr(module, \"__file__\", None)\n        if not path:\n            continue\n        if path.endswith(\".pyc\") or path.endswith(\".pyo\"):\n            path = path[:-1]\n        _check_file(modify_times, path)\n    for path in _watched_files:\n        _check_file(modify_times, path)\n\n\ndef _check_file(modify_times, path):\n    try:\n        modified = os.stat(path).st_mtime\n    except Exception:\n        return\n    if path not in modify_times:\n        modify_times[path] = modified\n        return\n    if modify_times[path] != modified:\n        gen_log.info(\"%s modified; restarting server\", path)\n        _reload()\n\n\ndef _reload():\n    global _reload_attempted\n    _reload_attempted = True\n    for fn in _reload_hooks:\n        fn()\n    if hasattr(signal, \"setitimer\"):\n        # Clear the alarm signal set by\n        # ioloop.set_blocking_log_threshold so it doesn't fire\n        # after the exec.\n        signal.setitimer(signal.ITIMER_REAL, 0, 0)\n    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty\n    # string, we were (probably) invoked with -m and the effective path\n    # is about to change on re-exec.  Add the current directory to $PYTHONPATH\n    # to ensure that the new process sees the same path we did.\n    path_prefix = '.' + os.pathsep\n    if (sys.path[0] == '' and\n            not os.environ.get(\"PYTHONPATH\", \"\").startswith(path_prefix)):\n        os.environ[\"PYTHONPATH\"] = (path_prefix +\n                                    os.environ.get(\"PYTHONPATH\", \"\"))\n    if not _has_execv:\n        subprocess.Popen([sys.executable] + sys.argv)\n        sys.exit(0)\n    else:\n        try:\n            os.execv(sys.executable, [sys.executable] + sys.argv)\n        except OSError:\n            # Mac OS X versions prior to 10.6 do not support execv in\n            # a process that contains multiple threads.  Instead of\n            # re-executing in the current process, start a new one\n            # and cause the current process to exit.  This isn't\n            # ideal since the new process is detached from the parent\n            # terminal and thus cannot easily be killed with ctrl-C,\n            # but it's better than not being able to autoreload at\n            # all.\n            # Unfortunately the errno returned in this case does not\n            # appear to be consistent, so we can't easily check for\n            # this error specifically.\n            os.spawnv(os.P_NOWAIT, sys.executable,\n                      [sys.executable] + sys.argv)\n            # At this point the IOLoop has been closed and finally\n            # blocks will experience errors if we allow the stack to\n            # unwind, so just exit uncleanly.\n            os._exit(0)\n\n\n_USAGE = \"\"\"\\\nUsage:\n  python -m tornado.autoreload -m module.to.run [args...]\n  python -m tornado.autoreload path/to/script.py [args...]\n\"\"\"\n\n\ndef main():\n    \"\"\"Command-line wrapper to re-run a script whenever its source changes.\n\n    Scripts may be specified by filename or module name::\n\n        python -m tornado.autoreload -m tornado.test.runtests\n        python -m tornado.autoreload tornado/test/runtests.py\n\n    Running a script with this wrapper is similar to calling\n    `tornado.autoreload.wait` at the end of the script, but this wrapper\n    can catch import-time problems like syntax errors that would otherwise\n    prevent the script from reaching its call to `wait`.\n    \"\"\"\n    original_argv = sys.argv\n    sys.argv = sys.argv[:]\n    if len(sys.argv) >= 3 and sys.argv[1] == \"-m\":\n        mode = \"module\"\n        module = sys.argv[2]\n        del sys.argv[1:3]\n    elif len(sys.argv) >= 2:\n        mode = \"script\"\n        script = sys.argv[1]\n        sys.argv = sys.argv[1:]\n    else:\n        print(_USAGE, file=sys.stderr)\n        sys.exit(1)\n\n    try:\n        if mode == \"module\":\n            import runpy\n            runpy.run_module(module, run_name=\"__main__\", alter_sys=True)\n        elif mode == \"script\":\n            with open(script) as f:\n                # Execute the script in our namespace instead of creating\n                # a new one so that something that tries to import __main__\n                # (e.g. the unittest module) will see names defined in the\n                # script instead of just those defined in this module.\n                global __file__\n                __file__ = script\n                # If __package__ is defined, imports may be incorrectly\n                # interpreted as relative to this module.\n                global __package__\n                del __package__\n                exec_in(f.read(), globals(), globals())\n    except SystemExit as e:\n        logging.basicConfig()\n        gen_log.info(\"Script exited with status %s\", e.code)\n    except Exception as e:\n        logging.basicConfig()\n        gen_log.warning(\"Script exited with uncaught exception\", exc_info=True)\n        # If an exception occurred at import time, the file with the error\n        # never made it into sys.modules and so we won't know to watch it.\n        # Just to make sure we've covered everything, walk the stack trace\n        # from the exception and watch every file.\n        for (filename, lineno, name, line) in traceback.extract_tb(sys.exc_info()[2]):\n            watch(filename)\n        if isinstance(e, SyntaxError):\n            # SyntaxErrors are special:  their innermost stack frame is fake\n            # so extract_tb won't see it and we have to get the filename\n            # from the exception object.\n            watch(e.filename)\n    else:\n        logging.basicConfig()\n        gen_log.info(\"Script exited normally\")\n    # restore sys.argv so subsequent executions will include autoreload\n    sys.argv = original_argv\n\n    if mode == 'module':\n        # runpy did a fake import of the module as __main__, but now it's\n        # no longer in sys.modules.  Figure out where it is and watch it.\n        loader = pkgutil.get_loader(module)\n        if loader is not None:\n            watch(loader.get_filename())\n\n    wait()\n\n\nif __name__ == \"__main__\":\n    # See also the other __main__ block at the top of the file, which modifies\n    # sys.path before our imports\n    main()\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Autoreload Fails to Reload `__main__` Module with Relative Imports

**Description:**
When running a Tornado application using `autoreload` as the `__main__` module with relative imports, the autoreload mechanism does not properly reload the module. This results in the application not restarting as expected upon file changes.

**Reproduce the Issue:**
```python
# main.py
import os
import sys
from tornado import autoreload

# This import relies on relative imports
import myapp

print('Starting')
if 'MYAPP_STARTED' not in os.environ:
    os.environ['MYAPP_STARTED'] = '1'
    sys.stdout.flush()
    autoreload._reload()
```

**Expected Behavior:**
Upon running the script, "Starting" should be printed twice. The first print occurs initially, and the second print should happen after `autoreload` triggers a reload of the `__main__` module.

**Actual Behavior:**
Only "Starting" is printed once, indicating that the module was not reloaded as expected.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/autoreload.py
#!/usr/bin/env python
#
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Automatically restart the server when a source file is modified.

Most applications should not access this module directly.  Instead,
pass the keyword argument ``autoreload=True`` to the
`tornado.web.Application` constructor (or ``debug=True``, which
enables this setting and several others).  This will enable autoreload
mode as well as checking for changes to templates and static
resources.  Note that restarting is a destructive operation and any
requests in progress will be aborted when the process restarts.  (If
you want to disable autoreload while using other debug-mode features,
pass both ``debug=True`` and ``autoreload=False``).

This module can also be used as a command-line wrapper around scripts
such as unit test runners.  See the `main` method for details.

The command-line wrapper and Application debug modes can be used together.
This combination is encouraged as the wrapper catches syntax errors and
other import-time failures, while debug mode catches changes once
the server has started.

This module depends on `.IOLoop`, so it will not work in WSGI applications
and Google App Engine.  It also will not work correctly when `.HTTPServer`'s
multi-process mode is used.

Reloading loses any Python interpreter command-line arguments (e.g. ``-u``)
because it re-executes Python using ``sys.executable`` and ``sys.argv``.
Additionally, modifying these variables will cause reloading to behave
incorrectly.

"""

from __future__ import absolute_import, division, print_function

import os
import sys

# sys.path handling
# -----------------
#
# If a module is run with "python -m", the current directory (i.e. "")
# is automatically prepended to sys.path, but not if it is run as
# "path/to/file.py".  The processing for "-m" rewrites the former to
# the latter, so subsequent executions won't have the same path as the
# original.
#
# Conversely, when run as path/to/file.py, the directory containing
# file.py gets added to the path, which can cause confusion as imports
# may become relative in spite of the future import.
#
# We address the former problem by setting the $PYTHONPATH environment
# variable before re-execution so the new process will see the correct
# path.  We attempt to address the latter problem when tornado.autoreload
# is run as __main__, although we can't fix the general case because
# we cannot reliably reconstruct the original command line
# (http://bugs.python.org/issue14208).

if __name__ == "__main__":
    # This sys.path manipulation must come before our imports (as much
    # as possible - if we introduced a tornado.sys or tornado.os
    # module we'd be in trouble), or else our imports would become
    # relative again despite the future import.
    #
    # There is a separate __main__ block at the end of the file to call main().
    if sys.path[0] == os.path.dirname(__file__):
        del sys.path[0]

import functools
import logging
import os
import pkgutil  # type: ignore
import sys
import traceback
import types
import subprocess
import weakref

from tornado import ioloop
from tornado.log import gen_log
from tornado import process
from tornado.util import exec_in

try:
    import signal
except ImportError:
    signal = None

# os.execv is broken on Windows and can't properly parse command line
# arguments and executable name if they contain whitespaces. subprocess
# fixes that behavior.
_has_execv = sys.platform != 'win32'

_watched_files = set()
_reload_hooks = []
_reload_attempted = False
_io_loops = weakref.WeakKeyDictionary()  # type: ignore


def start(check_time=500):
    """Begins watching source files for changes.

    .. versionchanged:: 5.0
       The ``io_loop`` argument (deprecated since version 4.1) has been removed.
    """
    io_loop = ioloop.IOLoop.current()
    if io_loop in _io_loops:
        return
    _io_loops[io_loop] = True
    if len(_io_loops) > 1:
        gen_log.warning("tornado.autoreload started more than once in the same process")
    modify_times = {}
    callback = functools.partial(_reload_on_update, modify_times)
    scheduler = ioloop.PeriodicCallback(callback, check_time)
    scheduler.start()


def wait():
    """Wait for a watched file to change, then restart the process.

    Intended to be used at the end of scripts like unit test runners,
    to run the tests again after any source file changes (but see also
    the command-line interface in `main`)
    """
    io_loop = ioloop.IOLoop()
    start(io_loop)
    io_loop.start()


def watch(filename):
    """Add a file to the watch list.

    All imported modules are watched by default.
    """
    _watched_files.add(filename)


def add_reload_hook(fn):
    """Add a function to be called before reloading the process.

    Note that for open file and socket handles it is generally
    preferable to set the ``FD_CLOEXEC`` flag (using `fcntl` or
    ``tornado.platform.auto.set_close_exec``) instead
    of using a reload hook to close them.
    """
    _reload_hooks.append(fn)


def _reload_on_update(modify_times):
    if _reload_attempted:
        # We already tried to reload and it didn't work, so don't try again.
        return
    if process.task_id() is not None:
        # We're in a child process created by fork_processes.  If child
        # processes restarted themselves, they'd all restart and then
        # all call fork_processes again.
        return
    for module in list(sys.modules.values()):
        # Some modules play games with sys.modules (e.g. email/__init__.py
        # in the standard library), and occasionally this can cause strange
        # failures in getattr.  Just ignore anything that's not an ordinary
        # module.
        if not isinstance(module, types.ModuleType):
            continue
        path = getattr(module, "__file__", None)
        if not path:
            continue
        if path.endswith(".pyc") or path.endswith(".pyo"):
            path = path[:-1]
        _check_file(modify_times, path)
    for path in _watched_files:
        _check_file(modify_times, path)


def _check_file(modify_times, path):
    try:
        modified = os.stat(path).st_mtime
    except Exception:
        return
    if path not in modify_times:
        modify_times[path] = modified
        return
    if modify_times[path] != modified:
        gen_log.info("%s modified; restarting server", path)
        _reload()


def _reload():
    global _reload_attempted
    _reload_attempted = True
    for fn in _reload_hooks:
        fn()
    if hasattr(signal, "setitimer"):
        # Clear the alarm signal set by
        # ioloop.set_blocking_log_threshold so it doesn't fire
        # after the exec.
        signal.setitimer(signal.ITIMER_REAL, 0, 0)
    # sys.path fixes: see comments at top of file.  If sys.path[0] is an empty
    # string, we were (probably) invoked with -m and the effective path
    # is about to change on re-exec.  Add the current directory to $PYTHONPATH
    # to ensure that the new process sees the same path we did.
    path_prefix = '.' + os.pathsep
    if (sys.path[0] == '' and
            not os.environ.get("PYTHONPATH", "").startswith(path_prefix)):
        os.environ["PYTHONPATH"] = (path_prefix +
                                    os.environ.get("PYTHONPATH", ""))
    if not _has_execv:
        subprocess.Popen([sys.executable] + sys.argv)
        sys.exit(0)
    else:
        try:
            os.execv(sys.executable, [sys.executable] + sys.argv)
        except OSError:
            # Mac OS X versions prior to 10.6 do not support execv in
            # a process that contains multiple threads.  Instead of
            # re-executing in the current process, start a new one
            # and cause the current process to exit.  This isn't
            # ideal since the new process is detached from the parent
            # terminal and thus cannot easily be killed with ctrl-C,
            # but it's better than not being able to autoreload at
            # all.
            # Unfortunately the errno returned in this case does not
            # appear to be consistent, so we can't easily check for
            # this error specifically.
            os.spawnv(os.P_NOWAIT, sys.executable,
                      [sys.executable] + sys.argv)
            # At this point the IOLoop has been closed and finally
            # blocks will experience errors if we allow the stack to
            # unwind, so just exit uncleanly.
            os._exit(0)


_USAGE = """\
Usage:
  python -m tornado.autoreload -m module.to.run [args...]
  python -m tornado.autoreload path/to/script.py [args...]
"""


def main():
    """Command-line wrapper to re-run a script whenever its source changes.

    Scripts may be specified by filename or module name::

        python -m tornado.autoreload -m tornado.test.runtests
        python -m tornado.autoreload tornado/test/runtests.py

    Running a script with this wrapper is similar to calling
    `tornado.autoreload.wait` at the end of the script, but this wrapper
    can catch import-time problems like syntax errors that would otherwise
    prevent the script from reaching its call to `wait`.
    """
    original_argv = sys.argv
    sys.argv = sys.argv[:]
    if len(sys.argv) >= 3 and sys.argv[1] == "-m":
        mode = "module"
        module = sys.argv[2]
        del sys.argv[1:3]
    elif len(sys.argv) >= 2:
        mode = "script"
        script = sys.argv[1]
        sys.argv = sys.argv[1:]
    else:
        print(_USAGE, file=sys.stderr)
        sys.exit(1)

    try:
        if mode == "module":
            import runpy
            runpy.run_module(module, run_name="__main__", alter_sys=True)
        elif mode == "script":
            with open(script) 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__ = script
                # If __package__ is defined, imports may be incorrectly
                # interpreted as relative to this module.
                global __package__
                del __package__
                exec_in(f.read(), globals(), globals())
    except SystemExit as e:
        logging.basicConfig()
        gen_log.info("Script exited with status %s", e.code)
    except Exception as e:
        logging.basicConfig()
        gen_log.warning("Script exited with uncaught exception", exc_info=True)
        # If an exception occurred at import time, the file with the error
        # never made it into sys.modules and so we won't know to watch it.
        # Just to make sure we've covered everything, walk the stack trace
        # from the exception and watch every file.
        for (filename, lineno, name, line) in traceback.extract_tb(sys.exc_info()[2]):
            watch(filename)
        if isinstance(e, SyntaxError):
            # SyntaxErrors are special:  their innermost stack frame is fake
            # so extract_tb won't see it and we have to get the filename
            # from the exception object.
            watch(e.filename)
    else:
        logging.basicConfig()
        gen_log.info("Script exited normally")
    # restore sys.argv so subsequent executions will include autoreload
    sys.argv = original_argv

    if mode == 'module':
        # runpy did a fake import of the module as __main__, but now it's
        # no longer in sys.modules.  Figure out where it is and watch it.
        loader = pkgutil.get_loader(module)
        if loader is not None:
            watch(loader.get_filename())

    wait()


if __name__ == "__main__":
    # See also the other __main__ block at the top of the file, which modifies
    # sys.path before our imports
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user