Repository: tornadoweb/tornado
Pull request #2137 (2017-08-19 11:05:05)

Correctly clear and create a new ioloop during autoreload
After the removal of the deprecated `io_loop` arguments from all functions, the autoreload module stopped working as the wait function's usage was missed in the refactor. This resulted in the start function receiving an `IOLoop` object as its only argument which it then used as the `check_time` argument resulting in errors further down the line when the `check_time` is expected to be an int. This PR fixes that problem allowing the autoreload script to work correctly.

To the see the original bug just run the autoreload module, for example: `python -m tornado.autoreload -m tornado.test`, modify a test file after the first run completes and you'll get something like this:

```
[I 170819 12:02:37 testing:679] PASS
[I 170819 12:02:37 autoreload:306] Script exited with status False
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/rogan/code/tornado/tornado/autoreload.py", line 340, in <module>
    main()
  File "/home/rogan/code/tornado/tornado/autoreload.py", line 334, in main
    wait()
  File "/home/rogan/code/tornado/tornado/autoreload.py", line 139, in wait
    start(io_loop)
  File "/home/rogan/code/tornado/tornado/autoreload.py", line 127, in start
    scheduler = ioloop.PeriodicCallback(callback, check_time)
  File "/home/rogan/code/tornado/tornado/ioloop.py", line 1053, in __init__
    if callback_time <= 0:
TypeError: '<=' not supported between instances of 'AsyncIOLoop' and 'int'
```


Patch:
diff --git a/tornado/autoreload.py b/tornado/autoreload.py
index da1b100d..64204455 100644
--- a/tornado/autoreload.py
+++ b/tornado/autoreload.py
@@ -136,7 +136,7 @@ def wait():
     the command-line interface in `main`)
     """
     io_loop = ioloop.IOLoop()
-    start(io_loop)
+    io_loop.add_callback(start)
     io_loop.start()
 
 
diff --git a/tornado/curl_httpclient.py b/tornado/curl_httpclient.py
index 9a0402b5..e0ec3fba 100644
--- a/tornado/curl_httpclient.py
+++ b/tornado/curl_httpclient.py
@@ -261,6 +261,7 @@ class CurlAsyncHTTPClient(AsyncHTTPClient):
             queue=info["curl_start_time"] - info["request"].start_time,
             namelookup=curl.getinfo(pycurl.NAMELOOKUP_TIME),
             connect=curl.getinfo(pycurl.CONNECT_TIME),
+            appconnect=curl.getinfo(pycurl.APPCONNECT_TIME),
             pretransfer=curl.getinfo(pycurl.PRETRANSFER_TIME),
             starttransfer=curl.getinfo(pycurl.STARTTRANSFER_TIME),
             total=curl.getinfo(pycurl.TOTAL_TIME),
diff --git a/tornado/httputil.py b/tornado/httputil.py
index a98273ae..f2b289b3 100755
--- a/tornado/httputil.py
+++ b/tornado/httputil.py
@@ -467,8 +467,7 @@ class HTTPServerRequest(object):
     def __repr__(self):
         attrs = ("protocol", "host", "method", "uri", "version", "remote_ip")
         args = ", ".join(["%s=%r" % (n, getattr(self, n)) for n in attrs])
-        return "%s(%s, headers=%s)" % (
-            self.__class__.__name__, args, dict(self.headers))
+        return "%s(%s)" % (self.__class__.__name__, args)
 
 
 class HTTPInputError(Exception):


Test patch:
diff --git a/tornado/test/httputil_test.py b/tornado/test/httputil_test.py
index 7ac79925..1521ca03 100644
--- a/tornado/test/httputil_test.py
+++ b/tornado/test/httputil_test.py
@@ -418,6 +418,10 @@ class HTTPServerRequestTest(unittest.TestCase):
         requets = HTTPServerRequest(uri='/')
         self.assertIsInstance(requets.body, bytes)
 
+    def test_repr_does_not_contain_headers(self):
+        request = HTTPServerRequest(uri='/', headers={'Canary': 'Coal Mine'})
+        self.assertTrue('Canary' not in repr(request))
+
 
 class ParseRequestStartLineTest(unittest.TestCase):
     METHOD = "GET"