blob: bce2287e1875b2accee4f98e9f2b00da486e7e1b [file] [log] [blame]
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001"""Response classes used by urllib.
2
3The base class, addbase, defines a minimal file-like interface,
4including read() and readline(). The typical response object is an
5addinfourl instance, which defines an info() method that returns
6headers and a geturl() method that returns the url.
7"""
8
9class addbase(object):
10 """Base class for addinfo and addclosehook."""
11
12 # XXX Add a method to expose the timeout on the underlying socket?
13
14 def __init__(self, fp):
15 # TODO(jhylton): Is there a better way to delegate using io?
16 self.fp = fp
17 self.read = self.fp.read
18 self.readline = self.fp.readline
19 # TODO(jhylton): Make sure an object with readlines() is also iterable
Antoine Pitroub353c122009-02-11 00:39:14 +000020 if hasattr(self.fp, "readlines"):
21 self.readlines = self.fp.readlines
Jeremy Hylton1afc1692008-06-18 20:49:58 +000022 if hasattr(self.fp, "fileno"):
23 self.fileno = self.fp.fileno
24 else:
25 self.fileno = lambda: None
26 if hasattr(self.fp, "__iter__"):
27 self.__iter__ = self.fp.__iter__
28 if hasattr(self.fp, "__next__"):
29 self.__next__ = self.fp.__next__
30
31 def __repr__(self):
32 return '<%s at %r whose fp = %r>' % (self.__class__.__name__,
33 id(self), self.fp)
34
35 def close(self):
Brett Cannone73b2bb2011-03-15 18:45:13 -040036 if self.fp:
37 self.fp.close()
38 self.fp = None
Jeremy Hylton1afc1692008-06-18 20:49:58 +000039 self.read = None
40 self.readline = None
41 self.readlines = None
42 self.fileno = None
Brett Cannone73b2bb2011-03-15 18:45:13 -040043 self.__iter__ = None
44 self.__next__ = None
Jeremy Hylton1afc1692008-06-18 20:49:58 +000045
Jeremy Hyltonb476d592009-03-26 21:34:20 +000046 def __enter__(self):
47 if self.fp is None:
48 raise ValueError("I/O operation on closed file")
49 return self
50
51 def __exit__(self, type, value, traceback):
52 self.close()
53
Jeremy Hylton1afc1692008-06-18 20:49:58 +000054class addclosehook(addbase):
55 """Class to add a close hook to an open file."""
56
57 def __init__(self, fp, closehook, *hookargs):
58 addbase.__init__(self, fp)
59 self.closehook = closehook
60 self.hookargs = hookargs
61
62 def close(self):
63 addbase.close(self)
64 if self.closehook:
65 self.closehook(*self.hookargs)
66 self.closehook = None
67 self.hookargs = None
68
69class addinfo(addbase):
70 """class to add an info() method to an open file."""
71
72 def __init__(self, fp, headers):
73 addbase.__init__(self, fp)
74 self.headers = headers
75
76 def info(self):
77 return self.headers
78
79class addinfourl(addbase):
80 """class to add info() and geturl() methods to an open file."""
81
82 def __init__(self, fp, headers, url, code=None):
83 addbase.__init__(self, fp)
84 self.headers = headers
85 self.url = url
86 self.code = code
87
88 def info(self):
89 return self.headers
90
91 def getcode(self):
92 return self.code
93
94 def geturl(self):
95 return self.url