Repository: tornadoweb/tornado

Issue:
Ship LICENSE in pypi tarball
pypi package does not contain the LICENSE file
Updated python 3.6 and status and codecov to README.md
- Added status of build and codecov to README.md.
- Added python 3.6 to appveyor.yml


Discussion:

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -16,7 +16,6 @@
     "sphinx.ext.autodoc",
     "sphinx.ext.coverage",
     "sphinx.ext.doctest",
-    "sphinx.ext.extlinks",
     "sphinx.ext.intersphinx",
     "sphinx.ext.viewcode",
     ]
@@ -79,19 +78,6 @@
     ('index', 'tornado.tex', 'Tornado Documentation', 'The Tornado Authors', 'manual', False),
     ]
 
-# HACK: sphinx has limited support for substitutions with the |version|
-# variable, but there doesn't appear to be any way to use this in a link
-# target.
-# http://stackoverflow.com/questions/1227037/substitutions-inside-links-in-rest-sphinx
-# The extlink extension can be used to do link substitutions, but it requires a
-# portion of the url to be literally contained in the document.  Therefore,
-# this link must be referenced as :current_tarball:`z`
-extlinks = {
-    'current_tarball': (
-        'https://pypi.org/packages/source/t/tornado/tornado-%s.tar.g%%s' % version,
-        'tornado-%s.tar.g' % version),
-    }
-
 intersphinx_mapping = {
     'python': ('https://docs.python.org/3.5/', None),
     }
diff --git a/tornado/process.py b/tornado/process.py
--- a/tornado/process.py
+++ b/tornado/process.py
@@ -355,6 +355,10 @@ def _set_returncode(self, status):
         else:
             assert os.WIFEXITED(status)
             self.returncode = os.WEXITSTATUS(status)
+        # We've taken over wait() duty from the subprocess.Popen
+        # object. If we don't inform it of the process's return code,
+        # it will log a warning at destruction in python 3.6+.
+        self.proc.returncode = self.returncode
         if self._exit_callback:
             callback = self._exit_callback
             self._exit_callback = None
diff --git a/tornado/tcpclient.py b/tornado/tcpclient.py
--- a/tornado/tcpclient.py
+++ b/tornado/tcpclient.py
@@ -201,8 +201,12 @@ def _create_stream(self, max_buffer_size, af, addr, source_ip=None,
         socket_obj = socket.socket(af)
         if source_port_bind or source_ip_bind:
             # If the user requires binding also to a specific IP/port.
-            socket_obj.bind((source_ip_bind, source_port_bind))
-            # Fail loudly if unable to use the IP/port.
+            try:
+                socket_obj.bind((source_ip_bind, source_port_bind))
+            except socket.error:
+                socket_obj.close()
+                # Fail loudly if unable to use the IP/port.
+                raise
         try:
             stream = IOStream(socket_obj,
                               io_loop=self.io_loop,


Test patch:
diff --git a/maint/test/cython/tox.ini b/maint/test/cython/tox.ini
--- a/maint/test/cython/tox.ini
+++ b/maint/test/cython/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 # This currently segfaults on pypy.
-envlist = py27,py33,py34,py35
+envlist = py27,py33,py34,py35,py36
 
 [testenv]
 deps =
@@ -16,3 +16,4 @@ basepython =
            py33: python3.3
            py34: python3.4
            py35: python3.5
+           py36: python3.6
diff --git a/tornado/test/process_test.py b/tornado/test/process_test.py
--- a/tornado/test/process_test.py
+++ b/tornado/test/process_test.py
@@ -149,7 +149,7 @@ def test_subprocess(self):
                              stdin=Subprocess.STREAM,
                              stdout=Subprocess.STREAM, stderr=subprocess.STDOUT,
                              io_loop=self.io_loop)
-        self.addCleanup(lambda: os.kill(subproc.pid, signal.SIGTERM))
+        self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait()))
         subproc.stdout.read_until(b'>>> ', self.stop)
         self.wait()
         subproc.stdin.write(b"print('hello')\n")
@@ -170,7 +170,7 @@ def test_close_stdin(self):
                              stdin=Subprocess.STREAM,
                              stdout=Subprocess.STREAM, stderr=subprocess.STDOUT,
                              io_loop=self.io_loop)
-        self.addCleanup(lambda: os.kill(subproc.pid, signal.SIGTERM))
+        self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait()))
         subproc.stdout.read_until(b'>>> ', self.stop)
         self.wait()
         subproc.stdin.close()
@@ -186,7 +186,7 @@ def test_stderr(self):
                               r"import sys; sys.stderr.write('hello\n')"],
                              stderr=Subprocess.STREAM,
                              io_loop=self.io_loop)
-        self.addCleanup(lambda: os.kill(subproc.pid, signal.SIGTERM))
+        self.addCleanup(lambda: (subproc.proc.terminate(), subproc.proc.wait()))
         subproc.stderr.read_until(b'\n', self.stop)
         data = self.wait()
         self.assertEqual(data, b'hello\n')
diff --git a/tornado/testing.py b/tornado/testing.py
--- a/tornado/testing.py
+++ b/tornado/testing.py
@@ -656,7 +656,9 @@ def main(**kwargs):
 
     This test runner is essentially equivalent to `unittest.main` from
     the standard library, but adds support for tornado-style option
-    parsing and log formatting.
+    parsing and log formatting. It is *not* necessary to use this
+    `main` function to run tests using `AsyncTestCase`; these tests
+    are self-contained and can run with any test runner.
 
     The easiest way to run a test is via the command line::