Skip to content

[2.7] bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer #1040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 31, 2019
Merged

[2.7] bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer #1040

merged 2 commits into from
Dec 31, 2019

Conversation

orsenthil
Copy link
Member

@orsenthil orsenthil commented Apr 8, 2017

The problem and the solution has been described well in the msg: http://bugs.python.org/issue27973#msg286016

This just brings the patch to github.

https://bugs.python.org/issue27973

Misc/NEWS Outdated
@@ -42,6 +42,8 @@ Extension Modules
Library
-------

- bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed :. The second - is not needed.

try:
for _ in range(3):
fp = urllib.urlopen(self.FTP_TEST_FILE)
# closing fp is not required.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test can behave differently in CPython and PyPy. If fp can remain unclosed, maybe save it in a list, so that it will not be closed in all implementations? If the file is not closed explicitly it is worth to call test_support.gc_collect() after removing all references to it. This will make the behavior more predicable in all implementations.

for _ in range(3):
urllib.FancyURLopener().retrieve(
self.FTP_TEST_FILE,
tempfile.NamedTemporaryFile().name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NamedTemporaryFile object can be collected right after getting its name. Save a reference to tempfile.NamedTemporaryFile() until retrieve a file or better use a context manager.

@doctoryes
Copy link

Has this fix stalled? I'm able to reproduce this problem in Python 2.7.13 with the following steps:

  • Create a virtualenv.
  • STATIC_DEPS=true pip --no-cache-dir install lxml==3.4.4

These steps result in this error:

Collecting lxml==3.4.4
  Downloading lxml-3.4.4.tar.gz (3.5MB)
    100% |████████████████████████████████| 3.5MB 12.0MB/s
    Complete output from command python setup.py egg_info:
    Building lxml version 3.4.4.
    Latest version of libiconv is 1.15
    Downloading libiconv into libs/libiconv-1.15.tar.gz
    Unpacking libiconv-1.15.tar.gz into build/tmp
    Latest version of libxml2 is 2.9.5
    Downloading libxml2 into libs/libxml2-2.9.5.tar.gz
    Unpacking libxml2-2.9.5.tar.gz into build/tmp
    Latest version of libxslt is 1.1.30
    Downloading libxslt into libs/libxslt-1.1.30.tar.gz
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/5c/jyk57yxn3zl9cyv5gmn84hxm0000gp/T/pip-build-LY1sdH/lxml/setup.py", line 230, in <module>
        **setup_extra_options()
      File "/private/var/folders/5c/jyk57yxn3zl9cyv5gmn84hxm0000gp/T/pip-build-LY1sdH/lxml/setup.py", line 144, in setup_extra_options
        STATIC_CFLAGS, STATIC_BINARIES)
      File "setupinfo.py", line 57, in ext_modules
        multicore=OPTION_MULTICORE)
      File "buildlibxml.py", line 333, in build_libxml2xslt
        libxslt_dir  = unpack_tarball(download_libxslt(download_dir, libxslt_version), build_dir)
      File "buildlibxml.py", line 129, in download_libxslt
        version_re, filename, version=version)
      File "buildlibxml.py", line 182, in download_library
        urlretrieve(full_url, dest_filename)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/urllib.py", line 98, in urlretrieve
        return opener.retrieve(url, filename, reporthook, data)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/urllib.py", line 245, in retrieve
        fp = self.open(url, data)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/urllib.py", line 213, in open
        return getattr(self, name)(url)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/urllib.py", line 558, in open_ftp
        (fp, retrlen) = self.ftpcache[key].retrfile(file, type)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/urllib.py", line 906, in retrfile
        conn, retrlen = self.ftp.ntransfercmd(cmd)
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/ftplib.py", line 334, in ntransfercmd
        host, port = self.makepasv()
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/ftplib.py", line 312, in makepasv
        host, port = parse227(self.sendcmd('PASV'))
      File "/Users/jeskew/.pyenv/versions/2.7.13/lib/python2.7/ftplib.py", line 830, in parse227
        raise error_reply, resp
    IOError: [Errno ftp error] 200 Switching to Binary mode.

@@ -213,14 +214,44 @@ def test_context_argument(self):
self.assertIn("Python", response.read())


class urlopen_FTPTest(unittest.TestCase):
# TODO: https://github.com/python/pythondotorg/issues/1069
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that this TODO is no longer needed.


with test_support.transient_internet(self.FTP_TEST_FILE):
try:
for _ in range(3):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for _ in range(3): is used a couple of times in this class. I think the 3 should be replaced with a constant.

fp = urllib.urlopen(self.FTP_TEST_FILE)
# closing fp is not required.
except IOError as e:
self.fail("Failed FTP binary file open."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a space after this period (or a space just before the "Error" on the next line).

Copy link
Contributor

@benjaminp benjaminp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you still want to pursue this, it will need to be rebased and blurbed.

@bedevere-bot
Copy link

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

@orsenthil orsenthil changed the title bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer [2.7] bpo-27973 - Fix for urllib.urlretrieve() failing on second ftp transfer Dec 30, 2019
@orsenthil
Copy link
Member Author

I have made the requested changes; please review again.

@benjaminp - Please take a call to include the final 2.7 release. Thanks.

@bedevere-bot
Copy link

Thanks for making the requested changes!

@benjaminp: please review the changes made to this pull request.

Copy link
Contributor

@benjaminp benjaminp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is essentially a revert, it seems good.

@orsenthil orsenthil merged commit f82e59a into python:2.7 Dec 31, 2019
@orsenthil orsenthil deleted the issue27973 branch December 31, 2019 05:14
@bedevere-bot
Copy link

@orsenthil: Please replace # with GH- in the commit message next time. Thanks!

@pablogsal
Copy link
Member

This PR is failing in several 2.7 buildbots:

Tests result: FAILURE then FAILURE
test test_urllibnet failed -- Traceback (most recent call last):
  File "D:\cygwin\home\db3l\buildarea\2.7.bolen-windows7\build\lib\test\test_urllibnet.py", line 232, in test_multiple_ftp_retrieves
    "multiple times.\n Error message was : %s" % e)
AssertionError: Failed FTP retrieve while accessing ftp url multiple times.
 Error message was : [Errno 13] Permission denied: 'd:\\temp\\tmpiuquqa'

Example failure:

https://buildbot.python.org/all/#/builders/209/builds/4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants