aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSenthil Kumaran <orsenthil@gmail.com>2019-12-30 21:14:56 -0800
committerGitHub <noreply@github.com>2019-12-30 21:14:56 -0800
commitf82e59ac4020a64c262a925230a8eb190b652e87 (patch)
tree2190cbee5f6705c67102e49d50fb1d35d77c438e
parent[2.7] Minor C API documentation improvements. (GH-17699) (diff)
downloadcpython-f82e59ac4020a64c262a925230a8eb190b652e87.tar.gz
cpython-f82e59ac4020a64c262a925230a8eb190b652e87.tar.bz2
cpython-f82e59ac4020a64c262a925230a8eb190b652e87.zip
[2.7] bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer (#1040)
* bpo-27973: Fix urllib.urlretrieve failing on subsequent ftp transfers from the same host. * bpo-35411: Skip test_urllibnet FTP tests on Travis CI.
-rw-r--r--Lib/test/test_urllibnet.py39
-rw-r--r--Lib/urllib.py6
-rw-r--r--Misc/NEWS.d/next/Library/2019-12-30-07-59-34.bpo-27973.mgWXH1.rst2
3 files changed, 46 insertions, 1 deletions
diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py
index 3f2d8dcd43b..df118dc75d1 100644
--- a/Lib/test/test_urllibnet.py
+++ b/Lib/test/test_urllibnet.py
@@ -1,5 +1,7 @@
+import tempfile
import unittest
from test import test_support
+from test.test_urllib2net import skip_ftp_test_on_travis
import socket
import urllib
@@ -213,6 +215,40 @@ class urlopen_HttpsTests(unittest.TestCase):
self.assertIn("Python", response.read())
+class urlopen_FTPTest(unittest.TestCase):
+ FTP_TEST_FILE = 'ftp://www.pythontest.net/README'
+ NUM_FTP_RETRIEVES = 3
+
+ @skip_ftp_test_on_travis
+ def test_multiple_ftp_retrieves(self):
+
+ with test_support.transient_internet(self.FTP_TEST_FILE):
+ try:
+ for _ in range(self.NUM_FTP_RETRIEVES):
+ with tempfile.NamedTemporaryFile() as fp:
+ urllib.FancyURLopener().retrieve(self.FTP_TEST_FILE, fp.name)
+ except IOError as e:
+ self.fail("Failed FTP retrieve while accessing ftp url "
+ "multiple times.\n Error message was : %s" % e)
+
+ @skip_ftp_test_on_travis
+ def test_multiple_ftp_urlopen_same_host(self):
+ with test_support.transient_internet(self.FTP_TEST_FILE):
+ ftp_fds_to_close = []
+ try:
+ for _ in range(self.NUM_FTP_RETRIEVES):
+ fd = urllib.urlopen(self.FTP_TEST_FILE)
+ # test ftp open without closing fd as a supported scenario.
+ ftp_fds_to_close.append(fd)
+ except IOError as e:
+ self.fail("Failed FTP binary file open. "
+ "Error message was: %s" % e)
+ finally:
+ # close the open fds
+ for fd in ftp_fds_to_close:
+ fd.close()
+
+
def test_main():
test_support.requires('network')
with test_support.check_py3k_warnings(
@@ -220,7 +256,8 @@ def test_main():
test_support.run_unittest(URLTimeoutTest,
urlopenNetworkTests,
urlretrieveNetworkTests,
- urlopen_HttpsTests)
+ urlopen_HttpsTests,
+ urlopen_FTPTest)
if __name__ == "__main__":
test_main()
diff --git a/Lib/urllib.py b/Lib/urllib.py
index 156879dd0a1..87bcd94db5f 100644
--- a/Lib/urllib.py
+++ b/Lib/urllib.py
@@ -934,7 +934,13 @@ class ftpwrapper:
return (ftpobj, retrlen)
def endtransfer(self):
+ if not self.busy:
+ return
self.busy = 0
+ try:
+ self.ftp.voidresp()
+ except ftperrors():
+ pass
def close(self):
self.keepalive = False
diff --git a/Misc/NEWS.d/next/Library/2019-12-30-07-59-34.bpo-27973.mgWXH1.rst b/Misc/NEWS.d/next/Library/2019-12-30-07-59-34.bpo-27973.mgWXH1.rst
new file mode 100644
index 00000000000..d50f483889b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-12-30-07-59-34.bpo-27973.mgWXH1.rst
@@ -0,0 +1,2 @@
+Fix urllib.urlretrieve failing on subsequent ftp transfers from the same
+host.