Retrieve a URL into a temporary location on disk. Requires a URL argument. If a filename is passed, it is used as the temporary file location. The reporthook argument should be a callable that accepts a block number, a read size, and the total file size of the URL target.
(url, filename=None, reporthook=None, data=None)
| 221 | |
| 222 | _url_tempfiles = [] |
| 223 | def urlretrieve(url, filename=None, reporthook=None, data=None): |
| 224 | """ |
| 225 | Retrieve a URL into a temporary location on disk. |
| 226 | |
| 227 | Requires a URL argument. If a filename is passed, it is used as |
| 228 | the temporary file location. The reporthook argument should be |
| 229 | a callable that accepts a block number, a read size, and the |
| 230 | total file size of the URL target. The data argument should be |
| 231 | valid URL encoded data. |
| 232 | |
| 233 | If a filename is passed and the URL points to a local resource, |
| 234 | the result is a copy from local file to new file. |
| 235 | |
| 236 | Returns a tuple containing the path to the newly created |
| 237 | data file as well as the resulting HTTPMessage object. |
| 238 | """ |
| 239 | url_type, path = _splittype(url) |
| 240 | |
| 241 | with contextlib.closing(urlopen(url, data)) as fp: |
| 242 | headers = fp.info() |
| 243 | |
| 244 | # Just return the local path and the "headers" for file:// |
| 245 | # URLs. No sense in performing a copy unless requested. |
| 246 | if url_type == "file" and not filename: |
| 247 | return os.path.normpath(path), headers |
| 248 | |
| 249 | # Handle temporary file setup. |
| 250 | if filename: |
| 251 | tfp = open(filename, 'wb') |
| 252 | else: |
| 253 | tfp = tempfile.NamedTemporaryFile(delete=False) |
| 254 | filename = tfp.name |
| 255 | _url_tempfiles.append(filename) |
| 256 | |
| 257 | with tfp: |
| 258 | result = filename, headers |
| 259 | bs = 1024*8 |
| 260 | size = -1 |
| 261 | read = 0 |
| 262 | blocknum = 0 |
| 263 | if "content-length" in headers: |
| 264 | size = int(headers["Content-Length"]) |
| 265 | |
| 266 | if reporthook: |
| 267 | reporthook(blocknum, bs, size) |
| 268 | |
| 269 | while True: |
| 270 | block = fp.read(bs) |
| 271 | if not block: |
| 272 | break |
| 273 | read += len(block) |
| 274 | tfp.write(block) |
| 275 | blocknum += 1 |
| 276 | if reporthook: |
| 277 | reporthook(blocknum, bs, size) |
| 278 | |
| 279 | if size >= 0 and read < size: |
| 280 | raise ContentTooShortError( |
nothing calls this directly
no test coverage detected