summaryrefslogtreecommitdiffstats
path: root/Lib/urllib
diff options
context:
space:
mode:
authorSenthil Kumaran <senthil@uthcode.com>2014-04-20 16:41:29 (GMT)
committerSenthil Kumaran <senthil@uthcode.com>2014-04-20 16:41:29 (GMT)
commit6117e5d8e3f00f3677f07a29b4ec968a5ed8cd76 (patch)
tree0da26badccffeb64225879a989f56b2ba16b0666 /Lib/urllib
parent9077d24d7f85e09e53def11b2beeaf40749e2464 (diff)
downloadcpython-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.py61
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