| LEFT | RIGHT |
| 1 """An extensible library for opening URLs using a variety of protocols | 1 """An extensible library for opening URLs using a variety of protocols |
| 2 | 2 |
| 3 The simplest way to use this module is to call the urlopen function, | 3 The simplest way to use this module is to call the urlopen function, |
| 4 which accepts a string containing a URL or a Request object (described | 4 which accepts a string containing a URL or a Request object (described |
| 5 below). It opens the URL and returns the results as file-like | 5 below). It opens the URL and returns the results as file-like |
| 6 object; the returned object has some extra methods described below. | 6 object; the returned object has some extra methods described below. |
| 7 | 7 |
| 8 The OpenerDirector manages a collection of Handler objects that do | 8 The OpenerDirector manages a collection of Handler objects that do |
| 9 all the actual work. Each Handler implements a particular protocol or | 9 all the actual work. Each Handler implements a particular protocol or |
| 10 option. The OpenerDirector is a composite object that invokes the | 10 option. The OpenerDirector is a composite object that invokes the |
| (...skipping 1340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 dirs = dirs[1:] | 1351 dirs = dirs[1:] |
| 1352 try: | 1352 try: |
| 1353 fw = self.connect_ftp(user, passwd, host, port, dirs, req.timeout) | 1353 fw = self.connect_ftp(user, passwd, host, port, dirs, req.timeout) |
| 1354 type = file and 'I' or 'D' | 1354 type = file and 'I' or 'D' |
| 1355 for attr in attrs: | 1355 for attr in attrs: |
| 1356 attr, value = splitvalue(attr) | 1356 attr, value = splitvalue(attr) |
| 1357 if attr.lower() == 'type' and \ | 1357 if attr.lower() == 'type' and \ |
| 1358 value in ('a', 'A', 'i', 'I', 'd', 'D'): | 1358 value in ('a', 'A', 'i', 'I', 'd', 'D'): |
| 1359 type = value.upper() | 1359 type = value.upper() |
| 1360 fp, retrlen = fw.retrfile(file, type) | 1360 fp, retrlen = fw.retrfile(file, type) |
| 1361 fw.close() | |
| 1362 headers = "" | 1361 headers = "" |
| 1363 mtype = mimetypes.guess_type(req.full_url)[0] | 1362 mtype = mimetypes.guess_type(req.full_url)[0] |
| 1364 if mtype: | 1363 if mtype: |
| 1365 headers += "Content-type: %s\n" % mtype | 1364 headers += "Content-type: %s\n" % mtype |
| 1366 if retrlen is not None and retrlen >= 0: | 1365 if retrlen is not None and retrlen >= 0: |
| 1367 headers += "Content-length: %d\n" % retrlen | 1366 headers += "Content-length: %d\n" % retrlen |
| 1368 headers = email.message_from_string(headers) | 1367 headers = email.message_from_string(headers) |
| 1369 return addinfourl(fp, headers, req.full_url) | 1368 return addinfourl(fp, headers, req.full_url) |
| 1370 except ftplib.all_errors as msg: | 1369 except ftplib.all_errors as msg: |
| 1371 exc = URLError('ftp error: %s' % msg) | 1370 exc = URLError('ftp error: %s' % msg) |
| 1372 raise exc.with_traceback(sys.exc_info()[2]) | 1371 raise exc.with_traceback(sys.exc_info()[2]) |
| 1373 | 1372 |
| 1374 def connect_ftp(self, user, passwd, host, port, dirs, timeout): | 1373 def connect_ftp(self, user, passwd, host, port, dirs, timeout): |
| 1375 fw = ftpwrapper(user, passwd, host, port, dirs, timeout) | 1374 return ftpwrapper(user, passwd, host, port, dirs, timeout, |
| 1376 return fw | 1375 persistent=False) |
| 1377 | 1376 |
| 1378 class CacheFTPHandler(FTPHandler): | 1377 class CacheFTPHandler(FTPHandler): |
| 1379 # XXX would be nice to have pluggable cache strategies | 1378 # XXX would be nice to have pluggable cache strategies |
| 1380 # XXX this stuff is definitely not thread safe | 1379 # XXX this stuff is definitely not thread safe |
| 1381 def __init__(self): | 1380 def __init__(self): |
| 1382 self.cache = {} | 1381 self.cache = {} |
| 1383 self.timeout = {} | 1382 self.timeout = {} |
| 1384 self.soonest = 0 | 1383 self.soonest = 0 |
| 1385 self.delay = 60 | 1384 self.delay = 60 |
| 1386 self.max_conns = 16 | 1385 self.max_conns = 16 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 if v == self.soonest: | 1418 if v == self.soonest: |
| 1420 del self.cache[k] | 1419 del self.cache[k] |
| 1421 del self.timeout[k] | 1420 del self.timeout[k] |
| 1422 break | 1421 break |
| 1423 self.soonest = min(list(self.timeout.values())) | 1422 self.soonest = min(list(self.timeout.values())) |
| 1424 | 1423 |
| 1425 def clear_cache(self): | 1424 def clear_cache(self): |
| 1426 for conn in self.cache.values(): | 1425 for conn in self.cache.values(): |
| 1427 conn.close() | 1426 conn.close() |
| 1428 self.cache.clear() | 1427 self.cache.clear() |
| 1428 self.timeout.clear() |
| 1429 | 1429 |
| 1430 | 1430 |
| 1431 # Code move from the old urllib module | 1431 # Code move from the old urllib module |
| 1432 | 1432 |
| 1433 MAXFTPCACHE = 10 # Trim the ftp cache beyond this size | 1433 MAXFTPCACHE = 10 # Trim the ftp cache beyond this size |
| 1434 | 1434 |
| 1435 # Helper for non-unix systems | 1435 # Helper for non-unix systems |
| 1436 if os.name == 'nt': | 1436 if os.name == 'nt': |
| 1437 from nturl2path import url2pathname, pathname2url | 1437 from nturl2path import url2pathname, pathname2url |
| 1438 else: | 1438 else: |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2144 if _noheaders is None: | 2144 if _noheaders is None: |
| 2145 _noheaders = email.message_from_string("") | 2145 _noheaders = email.message_from_string("") |
| 2146 return _noheaders | 2146 return _noheaders |
| 2147 | 2147 |
| 2148 | 2148 |
| 2149 # Utility classes | 2149 # Utility classes |
| 2150 | 2150 |
| 2151 class ftpwrapper: | 2151 class ftpwrapper: |
| 2152 """Class used by open_ftp() for cache of open FTP connections.""" | 2152 """Class used by open_ftp() for cache of open FTP connections.""" |
| 2153 | 2153 |
| 2154 def __init__(self, user, passwd, host, port, dirs, timeout=None): | 2154 def __init__(self, user, passwd, host, port, dirs, timeout=None, |
| 2155 persistent=True): |
| 2155 self.user = user | 2156 self.user = user |
| 2156 self.passwd = passwd | 2157 self.passwd = passwd |
| 2157 self.host = host | 2158 self.host = host |
| 2158 self.port = port | 2159 self.port = port |
| 2159 self.dirs = dirs | 2160 self.dirs = dirs |
| 2160 self.timeout = timeout | 2161 self.timeout = timeout |
| 2161 self.refcount = 0 | 2162 self.refcount = 0 |
| 2162 self.closed = False | 2163 self.keepalive = persistent |
| 2163 self.init() | 2164 self.init() |
| 2164 | 2165 |
| 2165 def init(self): | 2166 def init(self): |
| 2166 import ftplib | 2167 import ftplib |
| 2167 self.busy = 0 | 2168 self.busy = 0 |
| 2168 self.ftp = ftplib.FTP() | 2169 self.ftp = ftplib.FTP() |
| 2169 self.ftp.connect(self.host, self.port, self.timeout) | 2170 self.ftp.connect(self.host, self.port, self.timeout) |
| 2170 self.ftp.login(self.user, self.passwd) | 2171 self.ftp.login(self.user, self.passwd) |
| 2171 for dir in self.dirs: | 2172 for dir in self.dirs: |
| 2172 self.ftp.cwd(dir) | 2173 self.ftp.cwd(dir) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2219 def endtransfer(self): | 2220 def endtransfer(self): |
| 2220 if not self.busy: | 2221 if not self.busy: |
| 2221 return | 2222 return |
| 2222 self.busy = 0 | 2223 self.busy = 0 |
| 2223 try: | 2224 try: |
| 2224 self.ftp.voidresp() | 2225 self.ftp.voidresp() |
| 2225 except ftperrors(): | 2226 except ftperrors(): |
| 2226 pass | 2227 pass |
| 2227 | 2228 |
| 2228 def close(self): | 2229 def close(self): |
| 2229 self.closed = True | 2230 self.keepalive = False |
| 2230 if self.refcount <= 0: | 2231 if self.refcount <= 0: |
| 2231 self.real_close() | 2232 self.real_close() |
| 2232 | 2233 |
| 2233 def file_close(self): | 2234 def file_close(self): |
| 2234 self.endtransfer() | 2235 self.endtransfer() |
| 2235 self.refcount -= 1 | 2236 self.refcount -= 1 |
| 2236 if self.refcount <= 0 and self.closed: | 2237 if self.refcount <= 0 and not self.keepalive: |
| 2237 self.real_close() | 2238 self.real_close() |
| 2238 | 2239 |
| 2239 def real_close(self): | 2240 def real_close(self): |
| 2240 self.endtransfer() | 2241 self.endtransfer() |
| 2241 try: | 2242 try: |
| 2242 self.ftp.close() | 2243 self.ftp.close() |
| 2243 except ftperrors(): | 2244 except ftperrors(): |
| 2244 pass | 2245 pass |
| 2245 | 2246 |
| 2246 # Proxy handling | 2247 # Proxy handling |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2488 """ | 2489 """ |
| 2489 if getproxies_environment(): | 2490 if getproxies_environment(): |
| 2490 return proxy_bypass_environment(host) | 2491 return proxy_bypass_environment(host) |
| 2491 else: | 2492 else: |
| 2492 return proxy_bypass_registry(host) | 2493 return proxy_bypass_registry(host) |
| 2493 | 2494 |
| 2494 else: | 2495 else: |
| 2495 # By default use environment variables | 2496 # By default use environment variables |
| 2496 getproxies = getproxies_environment | 2497 getproxies = getproxies_environment |
| 2497 proxy_bypass = proxy_bypass_environment | 2498 proxy_bypass = proxy_bypass_environment |
| LEFT | RIGHT |