OLD | NEW |
| (Empty) |
1 """Class returned by TLSConnection.makefile().""" | |
2 | |
3 class FileObject: | |
4 """This class provides a file object interface to a | |
5 L{tlslite.TLSConnection.TLSConnection}. | |
6 | |
7 Call makefile() on a TLSConnection to create a FileObject instance. | |
8 | |
9 This class was copied, with minor modifications, from the | |
10 _fileobject class in socket.py. Note that fileno() is not | |
11 implemented.""" | |
12 | |
13 default_bufsize = 16384 #TREV: changed from 8192 | |
14 | |
15 def __init__(self, sock, mode='rb', bufsize=-1): | |
16 self._sock = sock | |
17 self.mode = mode # Not actually used in this version | |
18 if bufsize < 0: | |
19 bufsize = self.default_bufsize | |
20 self.bufsize = bufsize | |
21 self.softspace = False | |
22 if bufsize == 0: | |
23 self._rbufsize = 1 | |
24 elif bufsize == 1: | |
25 self._rbufsize = self.default_bufsize | |
26 else: | |
27 self._rbufsize = bufsize | |
28 self._wbufsize = bufsize | |
29 self._rbuf = "" # A string | |
30 self._wbuf = [] # A list of strings | |
31 | |
32 def _getclosed(self): | |
33 return self._sock is not None | |
34 closed = property(_getclosed, doc="True if the file is closed") | |
35 | |
36 def close(self): | |
37 try: | |
38 if self._sock: | |
39 for result in self._sock._decrefAsync(): #TREV | |
40 pass | |
41 finally: | |
42 self._sock = None | |
43 | |
44 def __del__(self): | |
45 try: | |
46 self.close() | |
47 except: | |
48 # close() may fail if __init__ didn't complete | |
49 pass | |
50 | |
51 def flush(self): | |
52 if self._wbuf: | |
53 buffer = "".join(self._wbuf) | |
54 self._wbuf = [] | |
55 self._sock.sendall(buffer) | |
56 | |
57 #def fileno(self): | |
58 # raise NotImplementedError() #TREV | |
59 | |
60 def write(self, data): | |
61 data = str(data) # XXX Should really reject non-string non-buffers | |
62 if not data: | |
63 return | |
64 self._wbuf.append(data) | |
65 if (self._wbufsize == 0 or | |
66 self._wbufsize == 1 and '\n' in data or | |
67 self._get_wbuf_len() >= self._wbufsize): | |
68 self.flush() | |
69 | |
70 def writelines(self, list): | |
71 # XXX We could do better here for very long lists | |
72 # XXX Should really reject non-string non-buffers | |
73 self._wbuf.extend(filter(None, map(str, list))) | |
74 if (self._wbufsize <= 1 or | |
75 self._get_wbuf_len() >= self._wbufsize): | |
76 self.flush() | |
77 | |
78 def _get_wbuf_len(self): | |
79 buf_len = 0 | |
80 for x in self._wbuf: | |
81 buf_len += len(x) | |
82 return buf_len | |
83 | |
84 def read(self, size=-1): | |
85 data = self._rbuf | |
86 if size < 0: | |
87 # Read until EOF | |
88 buffers = [] | |
89 if data: | |
90 buffers.append(data) | |
91 self._rbuf = "" | |
92 if self._rbufsize <= 1: | |
93 recv_size = self.default_bufsize | |
94 else: | |
95 recv_size = self._rbufsize | |
96 while True: | |
97 data = self._sock.recv(recv_size) | |
98 if not data: | |
99 break | |
100 buffers.append(data) | |
101 return "".join(buffers) | |
102 else: | |
103 # Read until size bytes or EOF seen, whichever comes first | |
104 buf_len = len(data) | |
105 if buf_len >= size: | |
106 self._rbuf = data[size:] | |
107 return data[:size] | |
108 buffers = [] | |
109 if data: | |
110 buffers.append(data) | |
111 self._rbuf = "" | |
112 while True: | |
113 left = size - buf_len | |
114 recv_size = max(self._rbufsize, left) | |
115 data = self._sock.recv(recv_size) | |
116 if not data: | |
117 break | |
118 buffers.append(data) | |
119 n = len(data) | |
120 if n >= left: | |
121 self._rbuf = data[left:] | |
122 buffers[-1] = data[:left] | |
123 break | |
124 buf_len += n | |
125 return "".join(buffers) | |
126 | |
127 def readline(self, size=-1): | |
128 data = self._rbuf | |
129 if size < 0: | |
130 # Read until \n or EOF, whichever comes first | |
131 if self._rbufsize <= 1: | |
132 # Speed up unbuffered case | |
133 assert data == "" | |
134 buffers = [] | |
135 recv = self._sock.recv | |
136 while data != "\n": | |
137 data = recv(1) | |
138 if not data: | |
139 break | |
140 buffers.append(data) | |
141 return "".join(buffers) | |
142 nl = data.find('\n') | |
143 if nl >= 0: | |
144 nl += 1 | |
145 self._rbuf = data[nl:] | |
146 return data[:nl] | |
147 buffers = [] | |
148 if data: | |
149 buffers.append(data) | |
150 self._rbuf = "" | |
151 while True: | |
152 data = self._sock.recv(self._rbufsize) | |
153 if not data: | |
154 break | |
155 buffers.append(data) | |
156 nl = data.find('\n') | |
157 if nl >= 0: | |
158 nl += 1 | |
159 self._rbuf = data[nl:] | |
160 buffers[-1] = data[:nl] | |
161 break | |
162 return "".join(buffers) | |
163 else: | |
164 # Read until size bytes or \n or EOF seen, whichever comes first | |
165 nl = data.find('\n', 0, size) | |
166 if nl >= 0: | |
167 nl += 1 | |
168 self._rbuf = data[nl:] | |
169 return data[:nl] | |
170 buf_len = len(data) | |
171 if buf_len >= size: | |
172 self._rbuf = data[size:] | |
173 return data[:size] | |
174 buffers = [] | |
175 if data: | |
176 buffers.append(data) | |
177 self._rbuf = "" | |
178 while True: | |
179 data = self._sock.recv(self._rbufsize) | |
180 if not data: | |
181 break | |
182 buffers.append(data) | |
183 left = size - buf_len | |
184 nl = data.find('\n', 0, left) | |
185 if nl >= 0: | |
186 nl += 1 | |
187 self._rbuf = data[nl:] | |
188 buffers[-1] = data[:nl] | |
189 break | |
190 n = len(data) | |
191 if n >= left: | |
192 self._rbuf = data[left:] | |
193 buffers[-1] = data[:left] | |
194 break | |
195 buf_len += n | |
196 return "".join(buffers) | |
197 | |
198 def readlines(self, sizehint=0): | |
199 total = 0 | |
200 list = [] | |
201 while True: | |
202 line = self.readline() | |
203 if not line: | |
204 break | |
205 list.append(line) | |
206 total += len(line) | |
207 if sizehint and total >= sizehint: | |
208 break | |
209 return list | |
210 | |
211 # Iterator protocols | |
212 | |
213 def __iter__(self): | |
214 return self | |
215 | |
216 def next(self): | |
217 line = self.readline() | |
218 if not line: | |
219 raise StopIteration | |
220 return line | |
OLD | NEW |