8000 in ftp cache pruning, avoid changing the size of a dict while iterati… · python/cpython@3c2dca6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3c2dca6

Browse files
committed
in ftp cache pruning, avoid changing the size of a dict while iterating over it (closes #21463)
Patch by Skyler Leigh Amador.
1 parent 4bb09c8 commit 3c2dca6

File tree

4 file 8000 s changed

+35
-2
lines changed

4 files changed

+35
-2
lines changed

Lib/test/test_urllib.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import email.message
88
import io
99
import unittest
10+
from unittest.mock import patch
1011
from test import support
1112
import os
1213
import sys
@@ -89,6 +90,26 @@ def unfakehttp(self):
8990
http.client.HTTPConnection = self._connection_class
9091

9192

93+
class FakeFTPMixin(object):
94+
def fakeftp(self):
95+
class FakeFtpWrapper(object):
96+
def __init__(self, user, passwd, host, port, dirs, timeout=None,
97+
persistent=True):
98+
pass
99+
100+
def retrfile(self, file, type):
101+
return io.BytesIO(), 0
102+
103+
def close(self):
104+
pass
105+
106+
self._ftpwrapper_class = urllib.request.ftpwrapper
107+
urllib.request.ftpwrapper = FakeFtpWrapper
108+
109+
def unfakeftp(self):
110+
urllib.request.ftpwrapper = self._ftpwrapper_class
111+
112+
92113
class urlopen_FileTests(unittest.TestCase):
93114
"""Test urlopen() opening a temporary file.
94115
@@ -195,7 +216,7 @@ def test_getproxies_environment_keep_no_proxies(self):
195216
self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com')
196217
self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com'))
197218

198-
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin):
219+
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin):
199220
"""Test urlopen() opening a fake http connection."""
200221

201222
def check_read(self, ver):
@@ -309,6 +330,15 @@ def test_ftp_nonexisting(self):
309330
self.assertFalse(e.exception.filename)
310331
self.assertTrue(e.exception.reason)
311332

333+
@patch.object(urllib.request, 'MAXFTPCACHE', 0)
334+
def test_ftp_cache_pruning(self):
335+
self.fakeftp()
336+
try:
337+
urllib.request.ftpcache['test'] = urllib.request.ftpwrapper('user', 'pass', 'localhost', 21, [])
338+
urlopen('ftp://localhost')
339+
finally:
340+
self.unfakeftp()
341+
312342

313343
def test_userpass_inurl(self):
314344
self.fakehttp(b"HTTP/1.0 200 OK\r\n\r\nHello!")

Lib/urllib/request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1911,7 +1911,7 @@ def open_ftp(self, url):
19111911
# XXX thread unsafe!
19121912
if len(self.ftpcache) > MAXFTPCACHE:
19131913
# Prune the cache, rather arbitrarily
1914-
for k in self.ftpcache.keys():
1914+
for k in list(self.ftpcache):
19151915
if k != key:
19161916
v = self.ftpcache[k]
19171917
del self.ftpcache[k]

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Fred Allen
3232
Ray Allen
3333
Billy G. Allie
3434
Kevin Altis
35+
Skyler Leigh Amador
3536
Joe Amenta
3637
A. Amoroso
3738
Mark Anacker

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Core and Builtins
2222
Library
2323
-------
2424

25+
- Issue #21463: In urllib.request, fix pruning of the FTP cache.
26+
2527
- Issue #21618: The subprocess module could fail to close open fds that were
2628
inherited by the calling process and already higher than POSIX resource
2729
limits would otherwise allow. On systems with a functioning /proc/self/fd

0 commit comments

Comments
 (0)
0