blob: 985964231093c4c0e7c2fb0781ac410dee419f6d [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):
36 self.read = None
37 self.readline = None
38 self.readlines = None
39 self.fileno = None
40 if self.fp: self.fp.close()
41 self.fp = None
42
Jeremy Hyltonb476d592009-03-26 21:34:20 +000043 def __enter__(self):
44 if self.fp is None:
45 raise ValueError("I/O operation on closed file")
46 return self
47
48 def __exit__(self, type, value, traceback):
49 self.close()
50
Jeremy Hylton1afc1692008-06-18 20:49:58 +000051class addclosehook(addbase):
52 """Class to add a close hook to an open file."""
53
54 def __init__(self, fp, closehook, *hookargs):
55 addbase.__init__(self, fp)
56 self.closehook = closehook
57 self.hookargs = hookargs
58
59 def close(self):
60 addbase.close(self)
61 if self.closehook:
62 self.closehook(*self.hookargs)
63 self.closehook = None
64 self.hookargs = None
65
66class addinfo(addbase):
67 """class to add an info() method to an open file."""
68
69 def __init__(self, fp, headers):
70 addbase.__init__(self, fp)
71 self.headers = headers
72
73 def info(self):
74 return self.headers
75
76class addinfourl(addbase):
77 """class to add info() and geturl() methods to an open file."""
78
79 def __init__(self, fp, headers, url, code=None):
80 addbase.__init__(self, fp)
81 self.headers = headers
82 self.url = url
83 self.code = code
84
85 def info(self):
86 return self.headers
87
88 def getcode(self):
89 return self.code
90
91 def geturl(self):
92 return self.url