diff options
author | Senthil Kumaran <senthil@uthcode.com> | 2014-04-20 16:41:29 (GMT) |
---|---|---|
committer | Senthil Kumaran <senthil@uthcode.com> | 2014-04-20 16:41:29 (GMT) |
commit | 6117e5d8e3f00f3677f07a29b4ec968a5ed8cd76 (patch) | |
tree | 0da26badccffeb64225879a989f56b2ba16b0666 /Lib/urllib | |
parent | 9077d24d7f85e09e53def11b2beeaf40749e2464 (diff) | |
download | cpython-6117e5d8e3f00f3677f07a29b4ec968a5ed8cd76.zip cpython-6117e5d8e3f00f3677f07a29b4ec968a5ed8cd76.tar.gz cpython-6117e5d8e3f00f3677f07a29b4ec968a5ed8cd76.tar.bz2 |
urllib.response object to use _TemporaryFileWrapper (and _TemporaryFileCloser)
facility. Provides a better way to handle file descriptor close.
Address issue #15002 . Patch contributed by Christian Theune.
Diffstat (limited to 'Lib/urllib')
-rw-r--r-- | Lib/urllib/response.py | 61 |
1 files changed, 19 insertions, 42 deletions
diff --git a/Lib/urllib/response.py b/Lib/urllib/response.py index 1cf1d1a..4a143b0 100644 --- a/Lib/urllib/response.py +++ b/Lib/urllib/response.py @@ -6,60 +6,39 @@ addinfourl instance, which defines an info() method that returns headers and a geturl() method that returns the url. """ -class addbase(object): - """Base class for addinfo and addclosehook.""" +import tempfile + +__all__ = ['addbase', 'addclosehook', 'addinfo', 'addinfourl'] + + +class addbase(tempfile._TemporaryFileWrapper): + """Base class for addinfo and addclosehook. Is a good idea for garbage collection.""" # XXX Add a method to expose the timeout on the underlying socket? def __init__(self, fp): - # TODO(jhylton): Is there a better way to delegate using io? + super(addbase, self).__init__(fp, '<urllib response>', delete=False) + # Keep reference around as this was part of the original API. self.fp = fp - self.read = self.fp.read - self.readline = self.fp.readline - # TODO(jhylton): Make sure an object with readlines() is also iterable - if hasattr(self.fp, "readlines"): - self.readlines = self.fp.readlines - if hasattr(self.fp, "fileno"): - self.fileno = self.fp.fileno - else: - self.fileno = lambda: None - - def __iter__(self): - # Assigning `__iter__` to the instance doesn't work as intended - # because the iter builtin does something like `cls.__iter__(obj)` - # and thus fails to find the _bound_ method `obj.__iter__`. - # Returning just `self.fp` works for built-in file objects but - # might not work for general file-like objects. - return iter(self.fp) def __repr__(self): return '<%s at %r whose fp = %r>' % (self.__class__.__name__, - id(self), self.fp) - - def close(self): - if self.fp: - self.fp.close() - self.fp = None - self.read = None - self.readline = None - self.readlines = None - self.fileno = None - self.__iter__ = None - self.__next__ = None + id(self), self.file) def __enter__(self): - if self.fp is None: + if self.fp.closed: raise ValueError("I/O operation on closed file") return self def __exit__(self, type, value, traceback): self.close() + class addclosehook(addbase): """Class to add a close hook to an open file.""" def __init__(self, fp, closehook, *hookargs): - addbase.__init__(self, fp) + super(addclosehook, self).__init__(fp) self.closehook = closehook self.hookargs = hookargs @@ -68,30 +47,28 @@ class addclosehook(addbase): self.closehook(*self.hookargs) self.closehook = None self.hookargs = None - addbase.close(self) + super(addclosehook, self).close() + class addinfo(addbase): """class to add an info() method to an open file.""" def __init__(self, fp, headers): - addbase.__init__(self, fp) + super(addinfo, self).__init__(fp) self.headers = headers def info(self): return self.headers -class addinfourl(addbase): + +class addinfourl(addinfo): """class to add info() and geturl() methods to an open file.""" def __init__(self, fp, headers, url, code=None): - addbase.__init__(self, fp) - self.headers = headers + super(addinfourl, self).__init__(fp, headers) self.url = url self.code = code - def info(self): - return self.headers - def getcode(self): return self.code |