Revision | 9148b572dfc8fcddce11c99348f95878a10f4006 (tree) |
---|---|
Zeit | 2011-02-20 12:50:23 |
Autor | azyobuzin <azyobuzin@user...> |
Commiter | azyobuzin |
IronPython更新
・ビルド通らないのを修正
@@ -4,6 +4,1932 @@ | ||
4 | 4 | <name>IronPython.Modules</name> |
5 | 5 | </assembly> |
6 | 6 | <members> |
7 | + <member name="T:ComponentAce.Compression.Libs.ZLib.Adler32"> | |
8 | + <summary> | |
9 | + This class represents adler32 checksum algorithm | |
10 | + </summary> | |
11 | + </member> | |
12 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Adler32.GetAdler32Checksum(System.Int64,System.Byte[],System.Int32,System.Int32)"> | |
13 | + <summary> | |
14 | + This static method returns adler32 checksum of the buffer data | |
15 | + </summary> | |
16 | + </member> | |
17 | + <member name="T:ComponentAce.Compression.Libs.ZLib.Deflate"> | |
18 | + <summary> | |
19 | + Implementation of the Deflate compression algorithm. | |
20 | + </summary> | |
21 | + </member> | |
22 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.MAX_MEM_LEVEL"> | |
23 | + <summary> | |
24 | + Maximum memory level | |
25 | + </summary> | |
26 | + </member> | |
27 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Z_DEFAULT_COMPRESSION"> | |
28 | + <summary> | |
29 | + Defalult compression method | |
30 | + </summary> | |
31 | + </member> | |
32 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.DEF_MEM_LEVEL"> | |
33 | + <summary> | |
34 | + Default memory level | |
35 | + </summary> | |
36 | + </member> | |
37 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.NeedMore"> | |
38 | + <summary> | |
39 | + block not completed, need more input or more output | |
40 | + </summary> | |
41 | + </member> | |
42 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.BlockDone"> | |
43 | + <summary> | |
44 | + Block internalFlush performed | |
45 | + </summary> | |
46 | + </member> | |
47 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.FinishStarted"> | |
48 | + <summary> | |
49 | + Finish started, need only more output at next deflate | |
50 | + </summary> | |
51 | + </member> | |
52 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.FinishDone"> | |
53 | + <summary> | |
54 | + finish done, accept no more input or output | |
55 | + </summary> | |
56 | + </member> | |
57 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.PRESET_DICT"> | |
58 | + <summary> | |
59 | + preset dictionary flag in zlib header | |
60 | + </summary> | |
61 | + </member> | |
62 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Z_DEFLATED"> | |
63 | + <summary> | |
64 | + The deflate compression method | |
65 | + </summary> | |
66 | + </member> | |
67 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Buf_size"> | |
68 | + <summary> | |
69 | + The size of the buffer | |
70 | + </summary> | |
71 | + </member> | |
72 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.REP_3_6"> | |
73 | + <summary> | |
74 | + repeat previous bit length 3-6 times (2 bits of repeat count) | |
75 | + </summary> | |
76 | + </member> | |
77 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.REPZ_3_10"> | |
78 | + <summary> | |
79 | + repeat a zero length 3-10 times (3 bits of repeat count) | |
80 | + </summary> | |
81 | + </member> | |
82 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.REPZ_11_138"> | |
83 | + <summary> | |
84 | + repeat a zero length 11-138 times (7 bits of repeat count) | |
85 | + </summary> | |
86 | + </member> | |
87 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.config_table"> | |
88 | + <summary> | |
89 | + Deflate class congiration table | |
90 | + </summary> | |
91 | + </member> | |
92 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.strm"> | |
93 | + <summary> | |
94 | + Pointer back to this zlib stream | |
95 | + </summary> | |
96 | + </member> | |
97 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.status"> | |
98 | + <summary> | |
99 | + As the name implies | |
100 | + </summary> | |
101 | + </member> | |
102 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.pending_buf"> | |
103 | + <summary> | |
104 | + Output still pending | |
105 | + </summary> | |
106 | + </member> | |
107 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.pending_buf_size"> | |
108 | + <summary> | |
109 | + Size of Pending_buf | |
110 | + </summary> | |
111 | + </member> | |
112 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.pending_out"> | |
113 | + <summary> | |
114 | + Next pending byte to output to the stream | |
115 | + </summary> | |
116 | + </member> | |
117 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.pending"> | |
118 | + <summary> | |
119 | + Number of bytes in the pending buffer | |
120 | + </summary> | |
121 | + </member> | |
122 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.noheader"> | |
123 | + <summary> | |
124 | + suppress zlib header and adler32 | |
125 | + </summary> | |
126 | + </member> | |
127 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.data_type"> | |
128 | + <summary> | |
129 | + UNKNOWN, BINARY or ASCII | |
130 | + </summary> | |
131 | + </member> | |
132 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.method"> | |
133 | + <summary> | |
134 | + STORED (for zip only) or DEFLATED | |
135 | + </summary> | |
136 | + </member> | |
137 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.last_flush"> | |
138 | + <summary> | |
139 | + Value of internalFlush parameter for previous deflate call | |
140 | + </summary> | |
141 | + </member> | |
142 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.w_size"> | |
143 | + <summary> | |
144 | + LZ77 Window size (32K by default) | |
145 | + </summary> | |
146 | + </member> | |
147 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.w_bits"> | |
148 | + <summary> | |
149 | + log2(w_size) (8..16) | |
150 | + </summary> | |
151 | + </member> | |
152 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.w_mask"> | |
153 | + <summary> | |
154 | + w_size - 1 | |
155 | + </summary> | |
156 | + </member> | |
157 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.window"> | |
158 | + <summary> | |
159 | + Sliding Window. Input bytes are ReadPos into the second half of the Window, | |
160 | + and move to the first half later to keep a dictionary of at least wSize | |
161 | + bytes. With this organization, matches are limited to a distance of | |
162 | + wSize-MAX_MATCH bytes, but this ensures that IO is always | |
163 | + performed with a length multiple of the block size. Also, it limits | |
164 | + the Window size to 64K, which is quite useful on MSDOS. | |
165 | + To do: use the user input buffer as sliding Window. | |
166 | + </summary> | |
167 | + </member> | |
168 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.window_size"> | |
169 | + <summary> | |
170 | + Actual size of Window: 2*wSize, except when the user input buffer is directly used as sliding Window. | |
171 | + </summary> | |
172 | + </member> | |
173 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.prev"> | |
174 | + <summary> | |
175 | + Link to older string with same hash index. To limit the size of this | |
176 | + array to 64K, this link is maintained only for the last 32K strings. | |
177 | + An index in this array is thus a Window index modulo 32K. | |
178 | + </summary> | |
179 | + </member> | |
180 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.head"> | |
181 | + <summary> | |
182 | + Heads of the hash chains or NIL. | |
183 | + </summary> | |
184 | + </member> | |
185 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.ins_h"> | |
186 | + <summary> | |
187 | + hash index of string to be inserted | |
188 | + </summary> | |
189 | + </member> | |
190 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.hash_size"> | |
191 | + <summary> | |
192 | + number of elements in hash table | |
193 | + </summary> | |
194 | + </member> | |
195 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.hash_bits"> | |
196 | + <summary> | |
197 | + log2(hash_size) | |
198 | + </summary> | |
199 | + </member> | |
200 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.hash_mask"> | |
201 | + <summary> | |
202 | + hash_size-1 | |
203 | + </summary> | |
204 | + </member> | |
205 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.hash_shift"> | |
206 | + <summary> | |
207 | + Number of bits by which ins_h must be shifted at each input | |
208 | + step. It must be such that after MIN_MATCH steps, the oldest | |
209 | + byte no longer takes part in the hash key, that is: | |
210 | + hash_shift * MIN_MATCH >= hash_bits | |
211 | + </summary> | |
212 | + </member> | |
213 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.block_start"> | |
214 | + <summary> | |
215 | + Window position at the beginning of the current output block. Gets negative when the Window is moved backwards. | |
216 | + </summary> | |
217 | + </member> | |
218 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.match_length"> | |
219 | + <summary> | |
220 | + length of best match | |
221 | + </summary> | |
222 | + </member> | |
223 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.prev_match"> | |
224 | + <summary> | |
225 | + previous match | |
226 | + </summary> | |
227 | + </member> | |
228 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.match_available"> | |
229 | + <summary> | |
230 | + set if previous match exists | |
231 | + </summary> | |
232 | + </member> | |
233 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.strstart"> | |
234 | + <summary> | |
235 | + start of string to insert | |
236 | + </summary> | |
237 | + </member> | |
238 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.match_start"> | |
239 | + <summary> | |
240 | + start of matching string | |
241 | + </summary> | |
242 | + </member> | |
243 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.lookahead"> | |
244 | + <summary> | |
245 | + number of valid bytes ahead in Window | |
246 | + </summary> | |
247 | + </member> | |
248 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.prev_length"> | |
249 | + <summary> | |
250 | + Length of the best match at previous step. Matches not greater than this | |
251 | + are discarded. This is used in the lazy match evaluation. | |
252 | + </summary> | |
253 | + </member> | |
254 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.max_chain_length"> | |
255 | + <summary> | |
256 | + To speed up deflation, hash chains are never searched beyond this | |
257 | + length. A higher limit improves compression ratio but degrades the speed. | |
258 | + </summary> | |
259 | + </member> | |
260 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.max_lazy_match"> | |
261 | + <summary> | |
262 | + Attempt to find a better match only when the current match is strictly | |
263 | + smaller than this value. This mechanism is used only for compression | |
264 | + levels >= 4. | |
265 | + </summary> | |
266 | + </member> | |
267 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate._level"> | |
268 | + <summary> | |
269 | + compression level (1..9) | |
270 | + </summary> | |
271 | + </member> | |
272 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.strategy"> | |
273 | + <summary> | |
274 | + favor or force Huffman coding | |
275 | + </summary> | |
276 | + </member> | |
277 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.good_match"> | |
278 | + <summary> | |
279 | + Use a faster search when the previous match is longer than this | |
280 | + </summary> | |
281 | + </member> | |
282 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.nice_match"> | |
283 | + <summary> | |
284 | + Stop searching when current match exceeds this | |
285 | + </summary> | |
286 | + </member> | |
287 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.dyn_ltree"> | |
288 | + <summary> | |
289 | + literal and length tree | |
290 | + </summary> | |
291 | + </member> | |
292 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.dyn_dtree"> | |
293 | + <summary> | |
294 | + distance tree | |
295 | + </summary> | |
296 | + </member> | |
297 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.bl_tree"> | |
298 | + <summary> | |
299 | + Huffman tree for bit lengths | |
300 | + </summary> | |
301 | + </member> | |
302 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.l_desc"> | |
303 | + <summary> | |
304 | + Desc for literal tree | |
305 | + </summary> | |
306 | + </member> | |
307 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.d_desc"> | |
308 | + <summary> | |
309 | + desc for distance tree | |
310 | + </summary> | |
311 | + </member> | |
312 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.bl_desc"> | |
313 | + <summary> | |
314 | + desc for bit length tree | |
315 | + </summary> | |
316 | + </member> | |
317 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.bl_count"> | |
318 | + <summary> | |
319 | + number of codes at each bit length for an optimal tree | |
320 | + </summary> | |
321 | + </member> | |
322 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.heap"> | |
323 | + <summary> | |
324 | + heap used to build the Huffman trees | |
325 | + </summary> | |
326 | + </member> | |
327 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.heap_len"> | |
328 | + <summary> | |
329 | + number of elements in the heap | |
330 | + </summary> | |
331 | + </member> | |
332 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.heap_max"> | |
333 | + <summary> | |
334 | + element of largest frequency | |
335 | + </summary> | |
336 | + </member> | |
337 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.depth"> | |
338 | + <summary> | |
339 | + Depth of each subtree used as tie breaker for trees of equal frequency | |
340 | + </summary> | |
341 | + </member> | |
342 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.l_buf"> | |
343 | + <summary> | |
344 | + index for literals or lengths | |
345 | + </summary> | |
346 | + </member> | |
347 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.lit_bufsize"> | |
348 | + <summary> | |
349 | + Size of match buffer for literals/lengths. There are 4 reasons for | |
350 | + limiting lit_bufsize to 64K: | |
351 | + - frequencies can be kept in 16 bit counters | |
352 | + - if compression is not successful for the first block, all input | |
353 | + data is still in the Window so we can still emit a stored block even | |
354 | + when input comes from standard input. (This can also be done for | |
355 | + all blocks if lit_bufsize is not greater than 32K.) | |
356 | + - if compression is not successful for a file smaller than 64K, we can | |
357 | + even emit a stored file instead of a stored block (saving 5 bytes). | |
358 | + This is applicable only for zip (not gzip or zlib). | |
359 | + - creating new Huffman trees less frequently may not provide fast | |
360 | + adaptation to changes in the input data statistics. (Take for | |
361 | + example a binary file with poorly compressible code followed by | |
362 | + a highly compressible string table.) Smaller buffer sizes give | |
363 | + fast adaptation but have of course the overhead of transmitting | |
364 | + trees more frequently. | |
365 | + - I can't count above 4 | |
366 | + </summary> | |
367 | + </member> | |
368 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.last_lit"> | |
369 | + <summary> | |
370 | + running index in l_buf | |
371 | + </summary> | |
372 | + </member> | |
373 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.d_buf"> | |
374 | + <summary> | |
375 | + index of pendig_buf | |
376 | + </summary> | |
377 | + </member> | |
378 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.opt_len"> | |
379 | + <summary> | |
380 | + bit length of current block with optimal trees | |
381 | + </summary> | |
382 | + </member> | |
383 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.static_len"> | |
384 | + <summary> | |
385 | + bit length of current block with static trees | |
386 | + </summary> | |
387 | + </member> | |
388 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.matches"> | |
389 | + <summary> | |
390 | + number of string matches in current block | |
391 | + </summary> | |
392 | + </member> | |
393 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.last_eob_len"> | |
394 | + <summary> | |
395 | + bit length of EOB code for last block | |
396 | + </summary> | |
397 | + </member> | |
398 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.bi_buf"> | |
399 | + <summary> | |
400 | + Output buffer. bits are inserted starting at the bottom (least | |
401 | + significant bits). | |
402 | + </summary> | |
403 | + </member> | |
404 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.bi_valid"> | |
405 | + <summary> | |
406 | + Number of valid bits in bi_buf. All bits above the last valid bit | |
407 | + are always zero. | |
408 | + </summary> | |
409 | + </member> | |
410 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.#ctor"> | |
411 | + <summary> | |
412 | + Default constructor | |
413 | + </summary> | |
414 | + </member> | |
415 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.lm_init"> | |
416 | + <summary> | |
417 | + Initialization | |
418 | + </summary> | |
419 | + </member> | |
420 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.tr_init"> | |
421 | + <summary> | |
422 | + Initialize the tree data structures for a new zlib stream. | |
423 | + </summary> | |
424 | + </member> | |
425 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.init_block"> | |
426 | + <summary> | |
427 | + Initializes block | |
428 | + </summary> | |
429 | + </member> | |
430 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.pqdownheap(System.Int16[],System.Int32)"> | |
431 | + <summary> | |
432 | + Restore the heap property by moving down the tree starting at node k, | |
433 | + exchanging a node with the smallest of its two sons if necessary, stopping | |
434 | + when the heap property is re-established (each father smaller than its | |
435 | + two sons). | |
436 | + </summary> | |
437 | + </member> | |
438 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.scan_tree(System.Int16[],System.Int32)"> | |
439 | + <summary> | |
440 | + Scan a literal or distance tree to determine the frequencies of the codes | |
441 | + in the bit length tree. | |
442 | + </summary> | |
443 | + </member> | |
444 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.build_bl_tree"> | |
445 | + <summary> | |
446 | + Construct the Huffman tree for the bit lengths and return the index in | |
447 | + bl_order of the last bit length code to send. | |
448 | + </summary> | |
449 | + </member> | |
450 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.send_all_trees(System.Int32,System.Int32,System.Int32)"> | |
451 | + <summary> | |
452 | + Send the header for a block using dynamic Huffman trees: the counts, the | |
453 | + lengths of the bit length codes, the literal tree and the distance tree. | |
454 | + IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. | |
455 | + </summary> | |
456 | + </member> | |
457 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.send_tree(System.Int16[],System.Int32)"> | |
458 | + <summary> | |
459 | + Send a literal or distance tree in compressed form, using the codes in | |
460 | + bl_tree. | |
461 | + </summary> | |
462 | + </member> | |
463 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.put_byte(System.Byte[],System.Int32,System.Int32)"> | |
464 | + <summary> | |
465 | + Output a byte on the stream. | |
466 | + IN assertion: there is enough room in Pending_buf. | |
467 | + </summary> | |
468 | + </member> | |
469 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.put_byte(System.Byte)"> | |
470 | + <summary> | |
471 | + Adds a byte to the buffer | |
472 | + </summary> | |
473 | + </member> | |
474 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate._tr_align"> | |
475 | + <summary> | |
476 | + Send one empty static block to give enough lookahead for inflate. | |
477 | + This takes 10 bits, of which 7 may remain in the bit buffer. | |
478 | + The current inflate code requires 9 bits of lookahead. If the | |
479 | + last two codes for the previous block (real code plus EOB) were coded | |
480 | + on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode | |
481 | + the last real code. In this case we send two empty static blocks instead | |
482 | + of one. (There are no problems if the previous block is stored or fixed.) | |
483 | + To simplify the code, we assume the worst case of last real code encoded | |
484 | + on one bit only. | |
485 | + </summary> | |
486 | + </member> | |
487 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate._tr_tally(System.Int32,System.Int32)"> | |
488 | + <summary> | |
489 | + Save the match info and tally the frequency counts. Return true if | |
490 | + the current block must be flushed. | |
491 | + </summary> | |
492 | + </member> | |
493 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.compress_block(System.Int16[],System.Int16[])"> | |
494 | + <summary> | |
495 | + Send the block data compressed using the given Huffman trees | |
496 | + </summary> | |
497 | + </member> | |
498 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.set_data_type"> | |
499 | + <summary> | |
500 | + Set the data type to ASCII or BINARY, using a crude approximation: | |
501 | + binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. | |
502 | + IN assertion: the fields freq of dyn_ltree are set and the total of all | |
503 | + frequencies does not exceed 64K (to fit in an int on 16 bit machines). | |
504 | + </summary> | |
505 | + </member> | |
506 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.bi_flush"> | |
507 | + <summary> | |
508 | + Flush the bit buffer, keeping at most 7 bits in it. | |
509 | + </summary> | |
510 | + </member> | |
511 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.bi_windup"> | |
512 | + <summary> | |
513 | + Flush the bit buffer and align the output on a byte boundary | |
514 | + </summary> | |
515 | + </member> | |
516 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.copy_block(System.Int32,System.Int32,System.Boolean)"> | |
517 | + <summary> | |
518 | + Copy a stored block, storing first the length and its | |
519 | + one's complement if requested. | |
520 | + </summary> | |
521 | + </member> | |
522 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.flush_block_only(System.Boolean)"> | |
523 | + <summary> | |
524 | + Flushes block | |
525 | + </summary> | |
526 | + </member> | |
527 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflate_stored(System.Int32)"> | |
528 | + <summary> | |
529 | + Copy without compression as much as possible from the input stream, return | |
530 | + the current block state. | |
531 | + This function does not insert new strings in the dictionary since | |
532 | + uncompressible data is probably not useful. This function is used | |
533 | + only for the level=0 compression option. | |
534 | + NOTE: this function should be optimized to avoid extra copying from | |
535 | + Window to Pending_buf. | |
536 | + </summary> | |
537 | + </member> | |
538 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate._tr_stored_block(System.Int32,System.Int32,System.Boolean)"> | |
539 | + <summary> | |
540 | + Send a stored block | |
541 | + </summary> | |
542 | + </member> | |
543 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate._tr_flush_block(System.Int32,System.Int32,System.Boolean)"> | |
544 | + <summary> | |
545 | + Determine the best encoding for the current block: dynamic trees, static | |
546 | + trees or store, and output the encoded block to the zip file. | |
547 | + </summary> | |
548 | + </member> | |
549 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.fill_window"> | |
550 | + <summary> | |
551 | + Fill the Window when the lookahead becomes insufficient. | |
552 | + Updates strstart and lookahead. | |
553 | + | |
554 | + IN assertion: lookahead less than MIN_LOOKAHEAD | |
555 | + OUT assertions: strstart less than or equal to window_size-MIN_LOOKAHEAD | |
556 | + At least one byte has been ReadPos, or _avail_in == 0; reads are | |
557 | + performed for at least two bytes (required for the zip translate_eol | |
558 | + option -- not supported here). | |
559 | + </summary> | |
560 | + </member> | |
561 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflate_fast(System.Int32)"> | |
562 | + <summary> | |
563 | + Compress as much as possible from the input stream, return the current | |
564 | + block state. | |
565 | + This function does not perform lazy evaluation of matches and inserts | |
566 | + new strings in the dictionary only for unmatched strings or for short | |
567 | + matches. It is used only for the fast compression options. | |
568 | + </summary> | |
569 | + </member> | |
570 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflate_slow(System.Int32)"> | |
571 | + <summary> | |
572 | + Same as above, but achieves better compression. We use a lazy | |
573 | + evaluation for matches: a match is finally adopted only if there is | |
574 | + no better match at the next Window position. | |
575 | + </summary> | |
576 | + </member> | |
577 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.longest_match(System.Int32)"> | |
578 | + <summary> | |
579 | + Finds the longest matching data part | |
580 | + </summary> | |
581 | + </member> | |
582 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateInit(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32,System.Int32)"> | |
583 | + <summary> | |
584 | + Deflate algorithm initialization | |
585 | + </summary> | |
586 | + <param name="strm">ZStream object</param> | |
587 | + <param name="level">Compression level</param> | |
588 | + <param name="bits">Window bits</param> | |
589 | + <returns>A result code</returns> | |
590 | + </member> | |
591 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateInit(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32)"> | |
592 | + <summary> | |
593 | + Initializes deflate algorithm | |
594 | + </summary> | |
595 | + <param name="strm">ZStream object</param> | |
596 | + <param name="level">Compression level</param> | |
597 | + <returns>Operation result result code</returns> | |
598 | + </member> | |
599 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateInit2(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32,System.Int32,System.Int32,System.Int32,ComponentAce.Compression.Libs.ZLib.CompressionStrategy)"> | |
600 | + <summary> | |
601 | + Deflate algorithm initialization | |
602 | + </summary> | |
603 | + <param name="strm">ZStream object</param> | |
604 | + <param name="level">Compression level</param> | |
605 | + <param name="method">Compression method</param> | |
606 | + <param name="windowBits">Window bits</param> | |
607 | + <param name="memLevel">Memory level</param> | |
608 | + <param name="strategy">Compression strategy</param> | |
609 | + <returns>Operation result code</returns> | |
610 | + </member> | |
611 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateReset(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
612 | + <summary> | |
613 | + Resets the current state of deflate object | |
614 | + </summary> | |
615 | + </member> | |
616 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateEnd"> | |
617 | + <summary> | |
618 | + Finish compression with deflate algorithm | |
619 | + </summary> | |
620 | + </member> | |
621 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateParams(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32,ComponentAce.Compression.Libs.ZLib.CompressionStrategy)"> | |
622 | + <summary> | |
623 | + Sets deflate algorithm parameters | |
624 | + </summary> | |
625 | + </member> | |
626 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflateSetDictionary(ComponentAce.Compression.Libs.ZLib.ZStream,System.Byte[],System.Int32)"> | |
627 | + <summary> | |
628 | + Sets deflate dictionary | |
629 | + </summary> | |
630 | + </member> | |
631 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.deflate(ComponentAce.Compression.Libs.ZLib.ZStream,ComponentAce.Compression.Libs.ZLib.FlushStrategy)"> | |
632 | + <summary> | |
633 | + Performs data compression with the deflate algorithm | |
634 | + </summary> | |
635 | + </member> | |
636 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.#cctor"> | |
637 | + <summary> | |
638 | + Static constructor initializes config_table | |
639 | + </summary> | |
640 | + </member> | |
641 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Deflate.level"> | |
642 | + <summary> | |
643 | + Compression level | |
644 | + </summary> | |
645 | + </member> | |
646 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Deflate.Pending"> | |
647 | + <summary> | |
648 | + Number of bytes in the pending buffer | |
649 | + </summary> | |
650 | + </member> | |
651 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Deflate.Pending_buf"> | |
652 | + <summary> | |
653 | + Output still pending | |
654 | + </summary> | |
655 | + </member> | |
656 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Deflate.Pending_out"> | |
657 | + <summary> | |
658 | + Next pending byte to output to the stream | |
659 | + </summary> | |
660 | + </member> | |
661 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Deflate.NoHeader"> | |
662 | + <summary> | |
663 | + suppress zlib header and adler32 | |
664 | + </summary> | |
665 | + </member> | |
666 | + <member name="T:ComponentAce.Compression.Libs.ZLib.Deflate.Config"> | |
667 | + <summary> | |
668 | + Deflate algorithm configuration parameters class | |
669 | + </summary> | |
670 | + </member> | |
671 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Config.good_length"> | |
672 | + <summary> | |
673 | + reduce lazy search above this match length | |
674 | + </summary> | |
675 | + </member> | |
676 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Config.max_lazy"> | |
677 | + <summary> | |
678 | + do not perform lazy search above this match length | |
679 | + </summary> | |
680 | + </member> | |
681 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Deflate.Config.nice_length"> | |
682 | + <summary> | |
683 | + quit search above this match length | |
684 | + </summary> | |
685 | + </member> | |
686 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Deflate.Config.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)"> | |
687 | + <summary> | |
688 | + Constructor which initializes class inner fields | |
689 | + </summary> | |
690 | + </member> | |
691 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.mode"> | |
692 | + <summary> | |
693 | + current inflate_block mode | |
694 | + </summary> | |
695 | + </member> | |
696 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.left"> | |
697 | + <summary> | |
698 | + if STORED, bytes left to copy | |
699 | + </summary> | |
700 | + </member> | |
701 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.table"> | |
702 | + <summary> | |
703 | + table lengths (14 bits) | |
704 | + </summary> | |
705 | + </member> | |
706 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.index"> | |
707 | + <summary> | |
708 | + index into blens (or border) | |
709 | + </summary> | |
710 | + </member> | |
711 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.blens"> | |
712 | + <summary> | |
713 | + bit lengths of codes | |
714 | + </summary> | |
715 | + </member> | |
716 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.bb"> | |
717 | + <summary> | |
718 | + bit length tree depth | |
719 | + </summary> | |
720 | + </member> | |
721 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.tb"> | |
722 | + <summary> | |
723 | + bit length decoding tree | |
724 | + </summary> | |
725 | + </member> | |
726 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.codes"> | |
727 | + <summary> | |
728 | + if CODES, current state | |
729 | + </summary> | |
730 | + </member> | |
731 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.last"> | |
732 | + <summary> | |
733 | + true if this block is the last block | |
734 | + </summary> | |
735 | + </member> | |
736 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.bitk"> | |
737 | + <summary> | |
738 | + bits in bit buffer | |
739 | + </summary> | |
740 | + </member> | |
741 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.bitb"> | |
742 | + <summary> | |
743 | + bit buffer | |
744 | + </summary> | |
745 | + </member> | |
746 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.hufts"> | |
747 | + <summary> | |
748 | + single malloc for tree space | |
749 | + </summary> | |
750 | + </member> | |
751 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.window"> | |
752 | + <summary> | |
753 | + sliding Window | |
754 | + </summary> | |
755 | + </member> | |
756 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.end"> | |
757 | + <summary> | |
758 | + one byte after sliding Window | |
759 | + </summary> | |
760 | + </member> | |
761 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.read"> | |
762 | + <summary> | |
763 | + Window ReadPos pointer | |
764 | + </summary> | |
765 | + </member> | |
766 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.write"> | |
767 | + <summary> | |
768 | + Window WritePos pointer | |
769 | + </summary> | |
770 | + </member> | |
771 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.needCheck"> | |
772 | + <summary> | |
773 | + need check | |
774 | + </summary> | |
775 | + </member> | |
776 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfBlocks.check"> | |
777 | + <summary> | |
778 | + check on output | |
779 | + </summary> | |
780 | + </member> | |
781 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.reset(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int64[])"> | |
782 | + <summary> | |
783 | + Resets this InfBlocks class instance | |
784 | + </summary> | |
785 | + </member> | |
786 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.proc(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32)"> | |
787 | + <summary> | |
788 | + Block processing functions | |
789 | + </summary> | |
790 | + </member> | |
791 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.free(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
792 | + <summary> | |
793 | + Frees inner buffers | |
794 | + </summary> | |
795 | + </member> | |
796 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.set_dictionary(System.Byte[],System.Int32,System.Int32)"> | |
797 | + <summary> | |
798 | + Sets dictionary | |
799 | + </summary> | |
800 | + </member> | |
801 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.sync_point"> | |
802 | + <summary> | |
803 | + Returns true if inflate is currently at the End of a block generated | |
804 | + by Z_SYNC_FLUSH or Z_FULL_FLUSH. | |
805 | + </summary> | |
806 | + </member> | |
807 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfBlocks.inflate_flush(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32)"> | |
808 | + <summary> | |
809 | + copy as much as possible from the sliding Window to the output area | |
810 | + </summary> | |
811 | + </member> | |
812 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.Window"> | |
813 | + <summary> | |
814 | + sliding window | |
815 | + </summary> | |
816 | + </member> | |
817 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.End"> | |
818 | + <summary> | |
819 | + one byte after sliding Window | |
820 | + </summary> | |
821 | + </member> | |
822 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.ReadPos"> | |
823 | + <summary> | |
824 | + Window ReadPos pointer | |
825 | + </summary> | |
826 | + </member> | |
827 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.WritePos"> | |
828 | + <summary> | |
829 | + Window WritePos pointer | |
830 | + </summary> | |
831 | + </member> | |
832 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.BitK"> | |
833 | + <summary> | |
834 | + bits in bit buffer | |
835 | + </summary> | |
836 | + </member> | |
837 | + <member name="P:ComponentAce.Compression.Libs.ZLib.InfBlocks.BitB"> | |
838 | + <summary> | |
839 | + bit buffer | |
840 | + </summary> | |
841 | + </member> | |
842 | + <member name="T:ComponentAce.Compression.Libs.ZLib.InflateCodesMode"> | |
843 | + <summary> | |
844 | + Inflate codes mode | |
845 | + </summary> | |
846 | + </member> | |
847 | + <member name="T:ComponentAce.Compression.Libs.ZLib.InfCodes"> | |
848 | + <summary> | |
849 | + This class is used by the InfBlocks class | |
850 | + </summary> | |
851 | + </member> | |
852 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.mode"> | |
853 | + <summary> | |
854 | + current inflate_codes mode | |
855 | + </summary> | |
856 | + </member> | |
857 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.count"> | |
858 | + <summary> | |
859 | + length | |
860 | + </summary> | |
861 | + </member> | |
862 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.tree"> | |
863 | + <summary> | |
864 | + pointer into tree | |
865 | + </summary> | |
866 | + </member> | |
867 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.tree_index"> | |
868 | + <summary> | |
869 | + current index of the tree | |
870 | + </summary> | |
871 | + </member> | |
872 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.need"> | |
873 | + <summary> | |
874 | + | |
875 | + </summary> | |
876 | + </member> | |
877 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.lbits"> | |
878 | + <summary> | |
879 | + ltree bits decoded per branch | |
880 | + </summary> | |
881 | + </member> | |
882 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.dbits"> | |
883 | + <summary> | |
884 | + dtree bits decoded per branch | |
885 | + </summary> | |
886 | + </member> | |
887 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.ltree"> | |
888 | + <summary> | |
889 | + literal/length/eob tree | |
890 | + </summary> | |
891 | + </member> | |
892 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.ltree_index"> | |
893 | + <summary> | |
894 | + literal/length/eob tree index | |
895 | + </summary> | |
896 | + </member> | |
897 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.dtree"> | |
898 | + <summary> | |
899 | + distance tree | |
900 | + </summary> | |
901 | + </member> | |
902 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InfCodes.dtree_index"> | |
903 | + <summary> | |
904 | + distance tree index | |
905 | + </summary> | |
906 | + </member> | |
907 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfCodes.#ctor(System.Int32,System.Int32,System.Int32[],System.Int32,System.Int32[],System.Int32,ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
908 | + <summary> | |
909 | + Constructor which takes literal, distance trees, corresponding bites decoded for branches, corresponding indexes and a ZStream object | |
910 | + </summary> | |
911 | + </member> | |
912 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfCodes.#ctor(System.Int32,System.Int32,System.Int32[],System.Int32[],ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
913 | + <summary> | |
914 | + Constructor which takes literal, distance trees, corresponding bites decoded for branches and a ZStream object | |
915 | + </summary> | |
916 | + </member> | |
917 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfCodes.proc(ComponentAce.Compression.Libs.ZLib.InfBlocks,ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32)"> | |
918 | + <summary> | |
919 | + Block processing method | |
920 | + </summary> | |
921 | + <param name="s">An instance of the InfBlocks class</param> | |
922 | + <param name="z">A ZStream object</param> | |
923 | + <param name="r">A result code</param> | |
924 | + </member> | |
925 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfCodes.free(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
926 | + <summary> | |
927 | + Frees allocated resources | |
928 | + </summary> | |
929 | + </member> | |
930 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfCodes.inflate_fast(System.Int32,System.Int32,System.Int32[],System.Int32,System.Int32[],System.Int32,ComponentAce.Compression.Libs.ZLib.InfBlocks,ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
931 | + <summary> | |
932 | + Fast inflate procedure. Called with number of bytes left to WritePos in Window at least 258 | |
933 | + (the maximum string length) and number of input bytes available | |
934 | + at least ten. The ten bytes are six bytes for the longest length/ | |
935 | + distance pair plus four bytes for overloading the bit buffer. | |
936 | + </summary> | |
937 | + </member> | |
938 | + <member name="T:ComponentAce.Compression.Libs.ZLib.InflateMode"> | |
939 | + <summary> | |
940 | + This enumeration contains modes of inflate processing | |
941 | + </summary> | |
942 | + </member> | |
943 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.METHOD"> | |
944 | + <summary> | |
945 | + waiting for method byte | |
946 | + </summary> | |
947 | + </member> | |
948 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.FLAG"> | |
949 | + <summary> | |
950 | + waiting for flag byte | |
951 | + </summary> | |
952 | + </member> | |
953 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DICT4"> | |
954 | + <summary> | |
955 | + four dictionary check bytes to go | |
956 | + </summary> | |
957 | + </member> | |
958 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DICT3"> | |
959 | + <summary> | |
960 | + three dictionary check bytes to go | |
961 | + </summary> | |
962 | + </member> | |
963 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DICT2"> | |
964 | + <summary> | |
965 | + two dictionary check bytes to go | |
966 | + </summary> | |
967 | + </member> | |
968 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DICT1"> | |
969 | + <summary> | |
970 | + one dictionary check byte to go | |
971 | + </summary> | |
972 | + </member> | |
973 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DICT0"> | |
974 | + <summary> | |
975 | + waiting for inflateSetDictionary | |
976 | + </summary> | |
977 | + </member> | |
978 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.BLOCKS"> | |
979 | + <summary> | |
980 | + decompressing blocks | |
981 | + </summary> | |
982 | + </member> | |
983 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.CHECK4"> | |
984 | + <summary> | |
985 | + four check bytes to go | |
986 | + </summary> | |
987 | + </member> | |
988 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.CHECK3"> | |
989 | + <summary> | |
990 | + three check bytes to go | |
991 | + </summary> | |
992 | + </member> | |
993 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.CHECK2"> | |
994 | + <summary> | |
995 | + two check bytes to go | |
996 | + </summary> | |
997 | + </member> | |
998 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.CHECK1"> | |
999 | + <summary> | |
1000 | + one check byte to go | |
1001 | + </summary> | |
1002 | + </member> | |
1003 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.DONE"> | |
1004 | + <summary> | |
1005 | + finished check, done | |
1006 | + </summary> | |
1007 | + </member> | |
1008 | + <member name="F:ComponentAce.Compression.Libs.ZLib.InflateMode.BAD"> | |
1009 | + <summary> | |
1010 | + got an error--stay here | |
1011 | + </summary> | |
1012 | + </member> | |
1013 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.mode"> | |
1014 | + <summary> | |
1015 | + current inflate mode | |
1016 | + </summary> | |
1017 | + </member> | |
1018 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.method"> | |
1019 | + <summary> | |
1020 | + if FLAGS, method byte | |
1021 | + </summary> | |
1022 | + </member> | |
1023 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.was"> | |
1024 | + <summary> | |
1025 | + computed check value | |
1026 | + </summary> | |
1027 | + </member> | |
1028 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.need"> | |
1029 | + <summary> | |
1030 | + stream check value | |
1031 | + </summary> | |
1032 | + </member> | |
1033 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.marker"> | |
1034 | + <summary> | |
1035 | + if BAD, inflateSync's marker bytes count | |
1036 | + </summary> | |
1037 | + </member> | |
1038 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.nowrap"> | |
1039 | + <summary> | |
1040 | + flag for no wrapper | |
1041 | + </summary> | |
1042 | + </member> | |
1043 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.wbits"> | |
1044 | + <summary> | |
1045 | + log2(Window size) (8..15, defaults to 15) | |
1046 | + </summary> | |
1047 | + </member> | |
1048 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Inflate.blocks"> | |
1049 | + <summary> | |
1050 | + current inflate_blocks state | |
1051 | + </summary> | |
1052 | + </member> | |
1053 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateReset(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1054 | + <summary> | |
1055 | + Resets the Inflate algorithm | |
1056 | + </summary> | |
1057 | + <param name="z">A ZStream object</param> | |
1058 | + <returns>A result code</returns> | |
1059 | + </member> | |
1060 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateEnd(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1061 | + <summary> | |
1062 | + Finishes the inflate algorithm processing | |
1063 | + </summary> | |
1064 | + <param name="z">A ZStream object</param> | |
1065 | + <returns>Operation result code</returns> | |
1066 | + </member> | |
1067 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateInit(ComponentAce.Compression.Libs.ZLib.ZStream,System.Int32)"> | |
1068 | + <summary> | |
1069 | + Initializes the inflate algorithm | |
1070 | + </summary> | |
1071 | + <param name="z">A ZStream object</param> | |
1072 | + <param name="windowBits">Window size</param> | |
1073 | + <returns>Operation result code</returns> | |
1074 | + </member> | |
1075 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflate(ComponentAce.Compression.Libs.ZLib.ZStream,ComponentAce.Compression.Libs.ZLib.FlushStrategy)"> | |
1076 | + <summary> | |
1077 | + Runs inflate algorithm | |
1078 | + </summary> | |
1079 | + <param name="z">A ZStream object</param> | |
1080 | + <param name="flush">Flush strategy</param> | |
1081 | + <returns>Operation result code</returns> | |
1082 | + </member> | |
1083 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateSetDictionary(ComponentAce.Compression.Libs.ZLib.ZStream,System.Byte[],System.Int32)"> | |
1084 | + <summary> | |
1085 | + Sets dictionary for the inflate operation | |
1086 | + </summary> | |
1087 | + <param name="z">A ZStream object</param> | |
1088 | + <param name="dictionary">An array of byte - dictionary</param> | |
1089 | + <param name="dictLength">Dictionary length</param> | |
1090 | + <returns>Operation result code</returns> | |
1091 | + </member> | |
1092 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateSync(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1093 | + <summary> | |
1094 | + Inflate synchronization | |
1095 | + </summary> | |
1096 | + <param name="z">A ZStream object</param> | |
1097 | + <returns>Operation result code</returns> | |
1098 | + </member> | |
1099 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Inflate.inflateSyncPoint(ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1100 | + <summary> | |
1101 | + Returns true if inflate is currently at the End of a block generated | |
1102 | + by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | |
1103 | + implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH | |
1104 | + but removes the length bytes of the resulting empty stored block. When | |
1105 | + decompressing, PPP checks that at the End of input packet, inflate is | |
1106 | + waiting for these length bytes. | |
1107 | + </summary> | |
1108 | + </member> | |
1109 | + <member name="T:ComponentAce.Compression.Libs.ZLib.InfTreeUtil"> | |
1110 | + <summary> | |
1111 | + Contains utility information for the InfTree class | |
1112 | + </summary> | |
1113 | + </member> | |
1114 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfTree.huft_build(System.Int32[],System.Int32,System.Int32,System.Int32,System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int32[])"> | |
1115 | + <summary> | |
1116 | + Given a list of code lengths and a maximum table size, make a set of | |
1117 | + tables to decode that set of codes. | |
1118 | + </summary> | |
1119 | + <returns>Return (int)ZLibResultCode.Z_OK on success, (int)ZLibResultCode.Z_DATA_ERROR if the given code set is incomplete (the tables are still built in this case), (int)ZLibResultCode.Z_DATA_ERROR if the input is invalid (an over-subscribed set of lengths), or (int)ZLibResultCode.Z_DATA_ERROR if not enough memory. | |
1120 | + </returns> | |
1121 | + </member> | |
1122 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfTree.inflate_trees_bits(System.Int32[],System.Int32[],System.Int32[],System.Int32[],ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1123 | + <summary> | |
1124 | + Build trees | |
1125 | + </summary> | |
1126 | + </member> | |
1127 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfTree.inflate_trees_dynamic(System.Int32,System.Int32,System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int32[],ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1128 | + <summary> | |
1129 | + Builds dynamic trees | |
1130 | + </summary> | |
1131 | + </member> | |
1132 | + <member name="M:ComponentAce.Compression.Libs.ZLib.InfTree.inflate_trees_fixed(System.Int32[],System.Int32[],System.Int32[][],System.Int32[][],ComponentAce.Compression.Libs.ZLib.ZStream)"> | |
1133 | + <summary> | |
1134 | + Build fixed trees | |
1135 | + </summary> | |
1136 | + </member> | |
1137 | + <member name="F:ComponentAce.Compression.Libs.ZLib.StaticTree.MAX_BL_BITS"> | |
1138 | + <summary> | |
1139 | + Bit length codes must not exceed MAX_BL_BITS bits | |
1140 | + </summary> | |
1141 | + </member> | |
1142 | + <member name="T:ComponentAce.Compression.Libs.ZLib.Tree"> | |
1143 | + <summary> | |
1144 | + This class represents a tree and is used in the Deflate class | |
1145 | + </summary> | |
1146 | + </member> | |
1147 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Tree.dyn_tree"> | |
1148 | + <summary> | |
1149 | + The dynamic tree | |
1150 | + </summary> | |
1151 | + </member> | |
1152 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Tree.max_code"> | |
1153 | + <summary> | |
1154 | + Largest code with non zero frequency | |
1155 | + </summary> | |
1156 | + </member> | |
1157 | + <member name="F:ComponentAce.Compression.Libs.ZLib.Tree.stat_desc"> | |
1158 | + <summary> | |
1159 | + the corresponding static tree | |
1160 | + </summary> | |
1161 | + </member> | |
1162 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Tree.d_code(System.Int32)"> | |
1163 | + <summary> | |
1164 | + Mapping from a distance to a distance code. dist is the distance - 1 and | |
1165 | + must not have side effects. _dist_code[256] and _dist_code[257] are never | |
1166 | + used. | |
1167 | + </summary> | |
1168 | + </member> | |
1169 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Tree.gen_bitlen(ComponentAce.Compression.Libs.ZLib.Deflate)"> | |
1170 | + <summary> | |
1171 | + Compute the optimal bit lengths for a tree and update the total bit length | |
1172 | + for the current block. | |
1173 | + IN assertion: the fields freq and dad are set, heap[heap_max] and | |
1174 | + above are the tree nodes sorted by increasing frequency. | |
1175 | + OUT assertions: the field count is set to the optimal bit length, the | |
1176 | + array bl_count contains the frequencies for each bit length. | |
1177 | + The length opt_len is updated; static_len is also updated if stree is | |
1178 | + not null. | |
1179 | + </summary> | |
1180 | + </member> | |
1181 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Tree.build_tree(ComponentAce.Compression.Libs.ZLib.Deflate)"> | |
1182 | + <summary> | |
1183 | + Construct one Huffman tree and assigns the code bit strings and lengths. | |
1184 | + Update the total bit length for the current block. | |
1185 | + IN assertion: the field freq is set for all tree elements. | |
1186 | + OUT assertions: the fields count and code are set to the optimal bit length | |
1187 | + and corresponding code. The length opt_len is updated; static_len is | |
1188 | + also updated if stree is not null. The field max_code is set. | |
1189 | + </summary> | |
1190 | + </member> | |
1191 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Tree.gen_codes(System.Int16[],System.Int32,System.Int16[])"> | |
1192 | + <summary> | |
1193 | + Generate the codes for a given tree and bit counts (which need not be | |
1194 | + optimal). | |
1195 | + IN assertion: the array bl_count contains the bit length statistics for | |
1196 | + the given tree and the field count is set for all tree elements. | |
1197 | + OUT assertion: the field code is set for all tree elements of non | |
1198 | + zero code length. | |
1199 | + </summary> | |
1200 | + </member> | |
1201 | + <member name="M:ComponentAce.Compression.Libs.ZLib.Tree.bi_reverse(System.Int32,System.Int32)"> | |
1202 | + <summary> | |
1203 | + Reverse the first count bits of a code, using straightforward code (a faster | |
1204 | + method would use a table) | |
1205 | + </summary> | |
1206 | + </member> | |
1207 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Tree.DynTree"> | |
1208 | + <summary> | |
1209 | + The dynamic tree | |
1210 | + </summary> | |
1211 | + </member> | |
1212 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Tree.MaxCode"> | |
1213 | + <summary> | |
1214 | + Largest code with non zero frequency | |
1215 | + </summary> | |
1216 | + </member> | |
1217 | + <member name="P:ComponentAce.Compression.Libs.ZLib.Tree.StatDesc"> | |
1218 | + <summary> | |
1219 | + the corresponding static tree | |
1220 | + </summary> | |
1221 | + </member> | |
1222 | + <member name="T:ComponentAce.Compression.Libs.ZLib.ZLibCompressionLevel"> | |
1223 | + <summary> | |
1224 | + Some constants for specifying compression levels. Methods which takes a compression level as a parameter expects an integer value from 0 to 9. You can either specify an integer value or use constants for some most widely used compression levels. | |
1225 | + </summary> | |
1226 | + </member> | |
1227 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibCompressionLevel.Z_NO_COMPRESSION"> | |
1228 | + <summary> | |
1229 | + No compression should be used at all. | |
1230 | + </summary> | |
1231 | + </member> | |
1232 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibCompressionLevel.Z_BEST_SPEED"> | |
1233 | + <summary> | |
1234 | + Minimal compression, but greatest speed. | |
1235 | + </summary> | |
1236 | + </member> | |
1237 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibCompressionLevel.Z_BEST_COMPRESSION"> | |
1238 | + <summary> | |
1239 | + Maximum compression, but slowest. | |
1240 | + </summary> | |
1241 | + </member> | |
1242 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibCompressionLevel.Z_DEFAULT_COMPRESSION"> | |
1243 | + <summary> | |
1244 | + Select default compression level (good compression, good speed). | |
1245 | + </summary> | |
1246 | + </member> | |
1247 | + <member name="T:ComponentAce.Compression.Libs.ZLib.CompressionStrategy"> | |
1248 | + <summary> | |
1249 | + Compression strategies. The strategy parameter is used to tune the compression algorithm. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. | |
1250 | + </summary> | |
1251 | + </member> | |
1252 | + <member name="F:ComponentAce.Compression.Libs.ZLib.CompressionStrategy.Z_FILTERED"> | |
1253 | + <summary> | |
1254 | + This strategy is designed for filtered data. Data which consists of mostly small values, with random distribution should use Z_FILTERED. With this strategy, less string matching is performed. | |
1255 | + </summary> | |
1256 | + </member> | |
1257 | + <member name="F:ComponentAce.Compression.Libs.ZLib.CompressionStrategy.Z_HUFFMAN_ONLY"> | |
1258 | + <summary> | |
1259 | + Z_HUFFMAN_ONLY forces Huffman encoding only (no string match) | |
1260 | + </summary> | |
1261 | + </member> | |
1262 | + <member name="F:ComponentAce.Compression.Libs.ZLib.CompressionStrategy.Z_DEFAULT_STRATEGY"> | |
1263 | + <summary> | |
1264 | + The default strategy is the most commonly used. With this strategy, string matching and huffman compression are balanced. | |
1265 | + </summary> | |
1266 | + </member> | |
1267 | + <member name="T:ComponentAce.Compression.Libs.ZLib.FlushStrategy"> | |
1268 | + <summary> | |
1269 | + Flush strategies | |
1270 | + </summary> | |
1271 | + </member> | |
1272 | + <member name="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_NO_FLUSH"> | |
1273 | + <summary> | |
1274 | + Do not internalFlush data, but just write data as normal to the output buffer. This is the normal way in which data is written to the output buffer. | |
1275 | + </summary> | |
1276 | + </member> | |
1277 | + <member name="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_PARTIAL_FLUSH"> | |
1278 | + <summary> | |
1279 | + Obsolete. You should use Z_SYNC_FLUSH instead. | |
1280 | + </summary> | |
1281 | + </member> | |
1282 | + <member name="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_SYNC_FLUSH"> | |
1283 | + <summary> | |
1284 | + All pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. | |
1285 | + </summary> | |
1286 | + </member> | |
1287 | + <member name="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FULL_FLUSH"> | |
1288 | + <summary> | |
1289 | + All output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade the compression. ZLib_InflateSync will locate points in the compression string where a full has been performed. | |
1290 | + </summary> | |
1291 | + </member> | |
1292 | + <member name="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"> | |
1293 | + <summary> | |
1294 | + Notifies the module that the input has now been exhausted. Pending input is processed, pending output is flushed and calls return with Z_STREAM_END if there was enough output space. | |
1295 | + </summary> | |
1296 | + </member> | |
1297 | + <member name="T:ComponentAce.Compression.Libs.ZLib.ZLibResultCode"> | |
1298 | + <summary> | |
1299 | + Results of operations in ZLib library | |
1300 | + </summary> | |
1301 | + </member> | |
1302 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"> | |
1303 | + <summary> | |
1304 | + No failure was encountered, the operation completed without problem. | |
1305 | + </summary> | |
1306 | + </member> | |
1307 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"> | |
1308 | + <summary> | |
1309 | + No failure was encountered, and the input has been exhausted. | |
1310 | + </summary> | |
1311 | + </member> | |
1312 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_NEED_DICT"> | |
1313 | + <summary> | |
1314 | + A preset dictionary is required for decompression of the data. | |
1315 | + </summary> | |
1316 | + </member> | |
1317 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_ERRNO"> | |
1318 | + <summary> | |
1319 | + An internal error occurred | |
1320 | + </summary> | |
1321 | + </member> | |
1322 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"> | |
1323 | + <summary> | |
1324 | + The stream structure was inconsistent | |
1325 | + </summary> | |
1326 | + </member> | |
1327 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"> | |
1328 | + <summary> | |
1329 | + Input data has been corrupted (for decompression). | |
1330 | + </summary> | |
1331 | + </member> | |
1332 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"> | |
1333 | + <summary> | |
1334 | + Memory allocation failed. | |
1335 | + </summary> | |
1336 | + </member> | |
1337 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_BUF_ERROR"> | |
1338 | + <summary> | |
1339 | + There was not enough space in the output buffer. | |
1340 | + </summary> | |
1341 | + </member> | |
1342 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_VERSION_ERROR"> | |
1343 | + <summary> | |
1344 | + The version supplied does not match that supported by the ZLib module. | |
1345 | + </summary> | |
1346 | + </member> | |
1347 | + <member name="T:ComponentAce.Compression.Libs.ZLib.DeflateState"> | |
1348 | + <summary> | |
1349 | + States of deflate operation | |
1350 | + </summary> | |
1351 | + </member> | |
1352 | + <member name="T:ComponentAce.Compression.Libs.ZLib.BlockType"> | |
1353 | + <summary> | |
1354 | + Data block types, i.e. binary or ascii text | |
1355 | + </summary> | |
1356 | + </member> | |
1357 | + <member name="T:ComponentAce.Compression.Libs.ZLib.ZLibUtil"> | |
1358 | + <summary> | |
1359 | + Helper class | |
1360 | + </summary> | |
1361 | + </member> | |
1362 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibUtil.MAX_WBITS"> | |
1363 | + <summary> | |
1364 | + Max Window size | |
1365 | + </summary> | |
1366 | + </member> | |
1367 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibUtil.PRESET_DICT"> | |
1368 | + <summary> | |
1369 | + preset dictionary flag in zlib header | |
1370 | + </summary> | |
1371 | + </member> | |
1372 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibUtil.zLibBufSize"> | |
1373 | + <summary> | |
1374 | + The size of the buffer | |
1375 | + </summary> | |
1376 | + </member> | |
1377 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibUtil.Z_DEFLATED"> | |
1378 | + <summary> | |
1379 | + Deflate compression method index | |
1380 | + </summary> | |
1381 | + </member> | |
1382 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZLibUtil.DIST_CODE_LEN"> | |
1383 | + <summary> | |
1384 | + see definition of array dist_code below | |
1385 | + </summary> | |
1386 | + </member> | |
1387 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.Identity(System.Int64)"> | |
1388 | + <summary> | |
1389 | + This method returns the literal value received | |
1390 | + </summary> | |
1391 | + <param name="literal">The literal to return</param> | |
1392 | + <returns>The received value</returns> | |
1393 | + </member> | |
1394 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.Identity(System.UInt64)"> | |
1395 | + <summary> | |
1396 | + This method returns the literal value received | |
1397 | + </summary> | |
1398 | + <param name="literal">The literal to return</param> | |
1399 | + <returns>The received value</returns> | |
1400 | + </member> | |
1401 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.Identity(System.Single)"> | |
1402 | + <summary> | |
1403 | + This method returns the literal value received | |
1404 | + </summary> | |
1405 | + <param name="literal">The literal to return</param> | |
1406 | + <returns>The received value</returns> | |
1407 | + </member> | |
1408 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.Identity(System.Double)"> | |
1409 | + <summary> | |
1410 | + This method returns the literal value received | |
1411 | + </summary> | |
1412 | + <param name="literal">The literal to return</param> | |
1413 | + <returns>The received value</returns> | |
1414 | + </member> | |
1415 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.URShift(System.Int32,System.Int32)"> | |
1416 | + <summary> | |
1417 | + Performs an unsigned bitwise right shift with the specified number | |
1418 | + </summary> | |
1419 | + <param name="number">Number to operate on</param> | |
1420 | + <param name="bits">Ammount of bits to shift</param> | |
1421 | + <returns>The resulting number from the shift operation</returns> | |
1422 | + </member> | |
1423 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.URShift(System.Int32,System.Int64)"> | |
1424 | + <summary> | |
1425 | + Performs an unsigned bitwise right shift with the specified number | |
1426 | + </summary> | |
1427 | + <param name="number">Number to operate on</param> | |
1428 | + <param name="bits">Ammount of bits to shift</param> | |
1429 | + <returns>The resulting number from the shift operation</returns> | |
1430 | + </member> | |
1431 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.URShift(System.Int64,System.Int32)"> | |
1432 | + <summary> | |
1433 | + Performs an unsigned bitwise right shift with the specified number | |
1434 | + </summary> | |
1435 | + <param name="number">Number to operate on</param> | |
1436 | + <param name="bits">Ammount of bits to shift</param> | |
1437 | + <returns>The resulting number from the shift operation</returns> | |
1438 | + </member> | |
1439 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.URShift(System.Int64,System.Int64)"> | |
1440 | + <summary> | |
1441 | + Performs an unsigned bitwise right shift with the specified number | |
1442 | + </summary> | |
1443 | + <param name="number">Number to operate on</param> | |
1444 | + <param name="bits">Ammount of bits to shift</param> | |
1445 | + <returns>The resulting number from the shift operation</returns> | |
1446 | + </member> | |
1447 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.ReadInput(System.IO.Stream,System.Byte[],System.Int32,System.Int32)"> | |
1448 | + <summary>Reads a number of characters from the current source Stream and writes the data to the target array at the specified index.</summary> | |
1449 | + <param name="sourceStream">The source Stream to ReadPos from.</param> | |
1450 | + <param name="target">Contains the array of characters ReadPos from the source Stream.</param> | |
1451 | + <param name="start">The starting index of the target array.</param> | |
1452 | + <param name="count">The maximum number of characters to ReadPos from the source Stream.</param> | |
1453 | + <returns>The number of characters ReadPos. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the End of the stream is reached.</returns> | |
1454 | + </member> | |
1455 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.ReadInput(System.IO.TextReader,System.Byte[],System.Int32,System.Int32)"> | |
1456 | + <summary>Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index.</summary> | |
1457 | + <param name="sourceTextReader">The source TextReader to ReadPos from</param> | |
1458 | + <param name="target">Contains the array of characteres ReadPos from the source TextReader.</param> | |
1459 | + <param name="start">The starting index of the target array.</param> | |
1460 | + <param name="count">The maximum number of characters to ReadPos from the source TextReader.</param> | |
1461 | + <returns>The number of characters ReadPos. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the End of the stream is reached.</returns> | |
1462 | + </member> | |
1463 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.ToByteArray(System.String)"> | |
1464 | + <summary> | |
1465 | + Converts a string to an array of bytes | |
1466 | + </summary> | |
1467 | + <param name="sourceString">The string to be converted</param> | |
1468 | + <returns>The new array of bytes</returns> | |
1469 | + </member> | |
1470 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.ToCharArray(System.Byte[])"> | |
1471 | + <summary> | |
1472 | + Converts an array of bytes to an array of chars | |
1473 | + </summary> | |
1474 | + <param name="byteArray">The array of bytes to convert</param> | |
1475 | + <returns>The new array of chars</returns> | |
1476 | + </member> | |
1477 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZLibUtil.CopyLargeArrayToSmall.CopyData"> | |
1478 | + <summary> | |
1479 | + Copies large array which was passed as srcBuf to the Initialize method into the destination array which were passes as destBuff | |
1480 | + </summary> | |
1481 | + <returns>The number of bytes copied</returns> | |
1482 | + </member> | |
1483 | + <member name="T:ComponentAce.Compression.Libs.ZLib.ZStream"> | |
1484 | + <summary> | |
1485 | + ZStream is used to store user data to compress/decompress. | |
1486 | + </summary> | |
1487 | + </member> | |
1488 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream.MAX_MEM_LEVEL"> | |
1489 | + <summary> | |
1490 | + Maximum memory level | |
1491 | + </summary> | |
1492 | + </member> | |
1493 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._next_in"> | |
1494 | + <summary> | |
1495 | + Next input byte array | |
1496 | + </summary> | |
1497 | + </member> | |
1498 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._next_in_index"> | |
1499 | + <summary> | |
1500 | + Index of the first byte in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in">input array</see>. | |
1501 | + </summary> | |
1502 | + </member> | |
1503 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._avail_in"> | |
1504 | + <summary> | |
1505 | + Number of bytes available at _next_in | |
1506 | + </summary> | |
1507 | + </member> | |
1508 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._total_in"> | |
1509 | + <summary> | |
1510 | + total nb of input bytes ReadPos so far | |
1511 | + </summary> | |
1512 | + </member> | |
1513 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._next_out"> | |
1514 | + <summary> | |
1515 | + Byte array for the next output block | |
1516 | + </summary> | |
1517 | + </member> | |
1518 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._next_out_index"> | |
1519 | + <summary> | |
1520 | + Index of the first byte in the _next_out array | |
1521 | + </summary> | |
1522 | + </member> | |
1523 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._avail_out"> | |
1524 | + <summary> | |
1525 | + Remaining free space at _next_out | |
1526 | + </summary> | |
1527 | + </member> | |
1528 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._total_out"> | |
1529 | + <summary> | |
1530 | + Total number of bytes in output array | |
1531 | + </summary> | |
1532 | + </member> | |
1533 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._msg"> | |
1534 | + <summary> | |
1535 | + A string to store operation result message (corresponding to result codes) | |
1536 | + </summary> | |
1537 | + </member> | |
1538 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._dstate"> | |
1539 | + <summary> | |
1540 | + A deflate object to perform data compression | |
1541 | + </summary> | |
1542 | + </member> | |
1543 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._istate"> | |
1544 | + <summary> | |
1545 | + Inflate object to perform data decompression | |
1546 | + </summary> | |
1547 | + </member> | |
1548 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream.data_type"> | |
1549 | + <summary> | |
1550 | + Best guess about the data type: ascii or binary | |
1551 | + </summary> | |
1552 | + </member> | |
1553 | + <member name="F:ComponentAce.Compression.Libs.ZLib.ZStream._adler"> | |
1554 | + <summary> | |
1555 | + A checksum computed with Adler algorithm | |
1556 | + </summary> | |
1557 | + </member> | |
1558 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit"> | |
1559 | + <summary> | |
1560 | + Initializes the internal stream state for decompression. The fields <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/>, <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> must be | |
1561 | + initialized before by the caller. If <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> is not <c>null</c> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> is large | |
1562 | + enough (the exact value depends on the compression method), <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit"/> determines the compression | |
1563 | + method from the ZLib header and allocates all data structures accordingly; otherwise the allocation will be deferred | |
1564 | + to the first call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1565 | + </summary> | |
1566 | + <returns> | |
1567 | + inflateInit returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"/> if there was not enough memory, | |
1568 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_VERSION_ERROR"/> if the ZLib library version is incompatible with the version assumed by the caller. | |
1569 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"/> is set to <c>null</c> if there is no error message. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit"/> does not perform any decompression | |
1570 | + apart from reading the ZLib header if present: this will be done by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. (So <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> | |
1571 | + may be modified, but <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> are unchanged.) | |
1572 | + </returns> | |
1573 | + </member> | |
1574 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit(System.Int32)"> | |
1575 | + <summary> | |
1576 | + This is another version of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit"/> with an extra parameter. The fields <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/>, <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> must be | |
1577 | + initialized before by the caller. If <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> is not <c>null</c> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> is large enough | |
1578 | + (the exact value depends on the compression method), <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit(System.Int32)"/> determines the compression method from | |
1579 | + the ZLib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first | |
1580 | + call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1581 | + </summary> | |
1582 | + <param name="windowBits">The <c>windowBits</c> parameter is the base two logarithm of the maximum window size (the size of the history buffer). | |
1583 | + It should be in the range <c>8..15</c> for this version of the library. The default value is 15 if <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit(System.Int32)"/> is used instead. | |
1584 | + If a compressed stream with a larger window size is given as input, <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> will return with the error code | |
1585 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> instead of trying to allocate a larger window.</param> | |
1586 | + <returns> | |
1587 | + inflateInit returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"/> if there was not enough memory, | |
1588 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if a parameter is invalid (such as a negative memLevel). <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"/> is set to null | |
1589 | + if there is no error message. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateInit(System.Int32)"/> does not perform any decompression apart from reading the ZLib header | |
1590 | + if present: this will be done by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. (So <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> may be modified, | |
1591 | + but <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> are unchanged.) | |
1592 | + </returns> | |
1593 | + </member> | |
1594 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"> | |
1595 | + <summary> | |
1596 | + <para>This method decompresses as much data as possible, and stops when the input buffer (<see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/>) becomes empty or | |
1597 | + the output buffer (<see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/>) becomes full. It may some introduce some output latency (reading input without producing any output) | |
1598 | + except when forced to flush. </para> | |
1599 | + <para>The detailed semantics are as follows. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> performs one or both of the following actions: </para> | |
1600 | + <para> | |
1601 | + <list type="bullet"> | |
1602 | + <item>Decompress more input starting at <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and update <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> | |
1603 | + accordingly. If not all input can be processed (because there is not enough room in the output buffer), <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> is updated and | |
1604 | + processing will resume at this point for the next call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. </item> | |
1605 | + <item>Provide more output starting at <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and update <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> | |
1606 | + accordingly. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> provides as much output as possible, until there is no more input data or no more space in | |
1607 | + the output buffer (see below about the <paramref name="flush"/> parameter).</item> | |
1608 | + </list> | |
1609 | + </para> | |
1610 | + </summary> | |
1611 | + <param name="flush"><see cref="T:ComponentAce.Compression.Libs.ZLib.FlushStrategy">Flush strategy</see> to use.</param> | |
1612 | + <remarks> | |
1613 | + <para>Before the call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>, the application should ensure that at least one of the actions is possible, by providing | |
1614 | + more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed | |
1615 | + output when it wants, for example when the output buffer is full (<c>avail_out == 0</c>), or after each call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1616 | + If <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> and with zero <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/>, it must be called again | |
1617 | + after making room in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out">output buffer</see> because there might be more output pending. </para> | |
1618 | + <para>If the parameter <paramref name="flush"/> is set to <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_SYNC_FLUSH"/>, <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> flushes | |
1619 | + as much output as possible to the output buffer. The flushing behavior of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> is not specified for values of | |
1620 | + the <paramref name="flush"/> parameter other than <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_SYNC_FLUSH"/> and <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/>, | |
1621 | + but the current implementation actually flushes as much output as possible anyway. </para> | |
1622 | + <para><see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> should normally be called until it returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> or an error. | |
1623 | + However if all decompression is to be performed in a single step (a single call of inflate), the parameter <paramref name="flush"/> | |
1624 | + should be set to <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/>. In this case all pending input is processed and all pending output is flushed; | |
1625 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been | |
1626 | + saved by the compressor for this purpose.) The next operation on this stream must be <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateEnd"/> to deallocate the decompression | |
1627 | + state. The use of <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/> is never required, but can be used to inform <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> that a faster | |
1628 | + routine may be used for the single <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> call. </para> | |
1629 | + <para>If a preset dictionary is needed at this point (see <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSetDictionary(System.Byte[],System.Int32)"/>), <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> sets strm-adler | |
1630 | + to the adler32 checksum of the dictionary chosen by the compressor and returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_NEED_DICT"/>; otherwise it | |
1631 | + sets strm->adler to the adler32 checksum of all output produced so far (that is, <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.total_out"/> bytes) and returns | |
1632 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/>, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> or an error code as described below. At the end of the stream, | |
1633 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>) checks that its computed adler32 checksum is equal to that saved by the compressor and returns | |
1634 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> only if the checksum is correct.</para> | |
1635 | + </remarks> | |
1636 | + <returns> | |
1637 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if some progress has been made (more input processed or more output produced), | |
1638 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> if the end of the compressed data has been reached and all uncompressed output has been produced, | |
1639 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_NEED_DICT"/> if a preset dictionary is needed at this point, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> if | |
1640 | + the input data was corrupted (input stream not conforming to the ZLib format or incorrect adler32 checksum), | |
1641 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if the stream structure was inconsistent (for example if <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> or | |
1642 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> was <c>null</c>), <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"/> if there was not enough memory, | |
1643 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_BUF_ERROR"/> if no progress is possible or if there was not enough room in the output buffer | |
1644 | + when <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/> is used. In the <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> case, the application | |
1645 | + may then call <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSync"/> to look for a good compression block. | |
1646 | + </returns> | |
1647 | + </member> | |
1648 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateEnd"> | |
1649 | + <summary> | |
1650 | + All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any | |
1651 | + pending output. | |
1652 | + </summary> | |
1653 | + <returns> | |
1654 | + inflateEnd returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> | |
1655 | + if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). | |
1656 | + </returns> | |
1657 | + </member> | |
1658 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSync"> | |
1659 | + <summary> | |
1660 | + Skips invalid compressed data until a full flush point (see the description of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)">deflate with Z_FULL_FLUSH</see>) can be found, | |
1661 | + or until all available input is skipped. No output is provided. | |
1662 | + </summary> | |
1663 | + <returns> | |
1664 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSync"/> returns <seec ref="ZLibResultCode.Z_OK"/> if a full flush point has been found, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_BUF_ERROR"/> | |
1665 | + if no more input was provided, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> if no flush point has been found, or | |
1666 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if the stream structure was inconsistent. In the success case, the application may save the current | |
1667 | + current value of <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.total_in"/> which indicates where valid compressed data was found. In the error case, the application may repeatedly | |
1668 | + call <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSync"/>, providing more input each time, until success or end of the input data. | |
1669 | + </returns> | |
1670 | + </member> | |
1671 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSetDictionary(System.Byte[],System.Int32)"> | |
1672 | + <summary> | |
1673 | + Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> if this call returned <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_NEED_DICT"/>. The dictionary chosen by the compressor can be determined from the Adler32 value returned by this call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. The compressor and decompresser must use exactly the same dictionary. | |
1674 | + </summary> | |
1675 | + <param name="dictionary">A byte array - a dictionary.</param> | |
1676 | + <param name="dictLength">The length of the dictionary.</param> | |
1677 | + <returns> | |
1678 | + inflateSetDictionary returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if a parameter is invalid (such as <c>null</c> dictionary) or the stream state is inconsistent, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> if the given dictionary doesn't match the expected one (incorrect Adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1679 | + </returns> | |
1680 | + </member> | |
1681 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"> | |
1682 | + <summary> | |
1683 | + Initializes the internal stream state for compression. | |
1684 | + </summary> | |
1685 | + <param name="level">An integer value from 0 to 9 indicating the desired compression level.</param> | |
1686 | + <returns> | |
1687 | + deflateInit returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"/> if there was not enough memory, | |
1688 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if level is not a valid compression level. <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"/> is set to <c>null</c> if there is | |
1689 | + no error message. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"/> does not perform any compression: this will be done by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1690 | + </returns> | |
1691 | + </member> | |
1692 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32,System.Int32)"> | |
1693 | + <summary> | |
1694 | + Initializes the internal stream state for compression. | |
1695 | + </summary> | |
1696 | + <param name="level">An integer value from 0 to 9 indicating the desired compression level.</param> | |
1697 | + <param name="bits"> The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the | |
1698 | + range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. | |
1699 | + The default value is 15 if deflateInit is used instead.</param> | |
1700 | + <returns> | |
1701 | + deflateInit returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_MEM_ERROR"/> if there was not enough memory, | |
1702 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if level is not a valid compression level. <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"/> is set to <c>null</c> if there | |
1703 | + is no error message. <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32,System.Int32)"/> does not perform any compression: this will be done by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1704 | + </returns> | |
1705 | + </member> | |
1706 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"> | |
1707 | + <summary> | |
1708 | + <para>Deflate compresses as much data as possible, and stops when the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in">input buffer</see> becomes empty or the | |
1709 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out">output buffer</see> becomes full. It may introduce some output latency (reading input without producing any output) | |
1710 | + except when forced to flush.</para> | |
1711 | + <para>The detailed semantics are as follows. deflate performs one or both of the following actions: | |
1712 | + <list type="bullet"> | |
1713 | + <item>Compress more input starting at <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and update <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> accordingly. | |
1714 | + If not all input can be processed (because there is not enough room in the output buffer), <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> | |
1715 | + are updated and processing will resume at this point for the next call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. </item> | |
1716 | + <item>Provide more output starting at <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and update <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> and <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> accordingly. | |
1717 | + This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should | |
1718 | + be set only when necessary (in interactive applications). Some output may be provided even if flush is not set.</item> | |
1719 | + </list> | |
1720 | + </para> | |
1721 | + </summary> | |
1722 | + <param name="flush">The <see cref="T:ComponentAce.Compression.Libs.ZLib.FlushStrategy">flush strategy</see> to use.</param> | |
1723 | + <remarks> | |
1724 | + <para> | |
1725 | + Before the call of <seec ref="deflate"/>, the application should ensure that at least one of the actions is possible, by providing | |
1726 | + more input and/or consuming more output, and updating <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> or <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> accordingly ; <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> | |
1727 | + should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full | |
1728 | + (<c>avail_out == 0</c>), or after each call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. If <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> | |
1729 | + and with zero <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/>, it must be called again after making room in the output buffer because there might be more output pending. | |
1730 | + </para> | |
1731 | + <para> | |
1732 | + If the parameter <paramref name="flush"/> is set to <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_SYNC_FLUSH"/>, all pending output is flushed to the | |
1733 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out">output buffer</see> and the output is aligned on a byte boundary, so that the decompressor can get all input | |
1734 | + data available so far. (In particular <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> is zero after the call if enough output space has been provided before the call.) | |
1735 | + Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. | |
1736 | + </para> | |
1737 | + <para> | |
1738 | + If flush is set to <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FULL_FLUSH"/>, all output is flushed as with <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_SYNC_FLUSH"/>, | |
1739 | + and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if | |
1740 | + random access is desired. Using <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FULL_FLUSH"/> too often can seriously degrade the compression. | |
1741 | + </para> | |
1742 | + </remarks> | |
1743 | + <returns> | |
1744 | + <para> | |
1745 | + If deflate returns with <c><see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> == 0</c>, this function must be called again with the same value of the flush | |
1746 | + parameter and more output space (updated <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/>), until the flush is complete (<see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> returns with | |
1747 | + non-zero <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/>). | |
1748 | + </para> | |
1749 | + <para> | |
1750 | + If the parameter <paramref name="flush"/> is set to <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/>, pending input is processed, pending | |
1751 | + output is flushed and deflate returns with <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> if there was enough output space ; | |
1752 | + if deflate returns with <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/>, this function must be called again with <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/> | |
1753 | + and more output space (updated <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/>) but no more input data, until it returns with <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> | |
1754 | + or an error. After deflate has returned <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/>, the only possible operation on the stream is | |
1755 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateEnd"/>. </para> | |
1756 | + <para> | |
1757 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/> can be used immediately after <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"/> if all the compression is to be | |
1758 | + done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return | |
1759 | + Z_STREAM_END, then it must be called again as described above. | |
1760 | + </para> | |
1761 | + <para> | |
1762 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> sets strm-> adler to the adler32 checksum of all input read so far (that is, <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.total_in"/> bytes). | |
1763 | + </para> | |
1764 | + <para> | |
1765 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> may update data_type if it can make a good guess about the input data type (<see cref="T:ComponentAce.Compression.Libs.ZLib.BlockType">Z_ASCII or Z_BINARY</see>). | |
1766 | + In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. | |
1767 | + </para> | |
1768 | + <para> | |
1769 | + <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if some progress has been made (more input processed or more output produced), | |
1770 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_END"/> if all input has been consumed and all output has been produced (only when flush is set to | |
1771 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.FlushStrategy.Z_FINISH"/>), <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if the stream state was inconsistent (for example if | |
1772 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> or <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> was <c>null</c>), <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_BUF_ERROR"/> if no progress is possible | |
1773 | + (for example <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"/> or <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> was zero). | |
1774 | + </para> | |
1775 | + </returns> | |
1776 | + </member> | |
1777 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateEnd"> | |
1778 | + <summary> | |
1779 | + All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending | |
1780 | + output. | |
1781 | + </summary> | |
1782 | + <returns> | |
1783 | + deflateEnd returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if the stream state was inconsistent, | |
1784 | + <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_DATA_ERROR"/> if the stream was freed prematurely (some input or output was discarded). In the error case, | |
1785 | + <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"/> may be set but then points to a static string (which must not be deallocated). | |
1786 | + </returns> | |
1787 | + </member> | |
1788 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateParams(System.Int32,ComponentAce.Compression.Libs.ZLib.CompressionStrategy)"> | |
1789 | + <summary> | |
1790 | + Dynamically update the compression level and compression strategy. The interpretation of level is as in <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"/>. | |
1791 | + This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data | |
1792 | + requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level | |
1793 | + (and may be flushed); the new level will take effect only at the next call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> | |
1794 | + </summary> | |
1795 | + <param name="level">An integer value indicating the desired compression level.</param> | |
1796 | + <param name="strategy">A <see cref="T:ComponentAce.Compression.Libs.ZLib.FlushStrategy">flush strategy</see> to use.</param> | |
1797 | + <remarks> | |
1798 | + Before the call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateParams(System.Int32,ComponentAce.Compression.Libs.ZLib.CompressionStrategy)"/>, the stream state must be set as for a call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>, since the | |
1799 | + currently available input may have to be compressed and flushed. In particular, <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> must be non-zero. | |
1800 | + </remarks> | |
1801 | + <returns> | |
1802 | + deflateParams returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if the source stream | |
1803 | + state was inconsistent or if a parameter was invalid, <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_BUF_ERROR"/> if <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"/> was zero. | |
1804 | + </returns> | |
1805 | + </member> | |
1806 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateSetDictionary(System.Byte[],System.Int32)"> | |
1807 | + <summary> | |
1808 | + Initializes the compression dictionary from the given byte sequence without producing any compressed output. This function must be called | |
1809 | + immediately after <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"/>, before any call of <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. The compressor and decompressor must use | |
1810 | + exactly the same dictionary (see <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.inflateSetDictionary(System.Byte[],System.Int32)"/>). | |
1811 | + </summary> | |
1812 | + <param name="dictionary">A byte array - a dictionary.</param> | |
1813 | + <param name="dictLength">The length of the dictionary byte array</param> | |
1814 | + <remarks> | |
1815 | + <para> | |
1816 | + The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, | |
1817 | + with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data | |
1818 | + to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. | |
1819 | + </para> | |
1820 | + <para>Depending on the size of the compression data structures selected by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateInit(System.Int32)"/>, a part of the dictionary may | |
1821 | + in effect be discarded, for example if the dictionary is larger than the window size in <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. Thus the strings most likely | |
1822 | + to be useful should be put at the end of the dictionary, not at the front.</para> | |
1823 | + <para>Upon return of this function, adler is set to the Adler32 value of the dictionary; the decompresser may later use this value to determine | |
1824 | + which dictionary has been used by the compressor. (The Adler32 value applies to the whole dictionary even if only a subset of the dictionary | |
1825 | + is actually used by the compressor.)</para> | |
1826 | + </remarks> | |
1827 | + <returns> | |
1828 | + deflateSetDictionary returns <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_OK"/> if success, or <see cref="F:ComponentAce.Compression.Libs.ZLib.ZLibResultCode.Z_STREAM_ERROR"/> if a parameter | |
1829 | + is invalid (such as <c>null</c> dictionary) or the stream state is inconsistent (for example if <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> has already been | |
1830 | + called for this stream or if the compression method is bsort). <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflateSetDictionary(System.Byte[],System.Int32)"/> does not perform any compression: | |
1831 | + this will be done by <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/>. | |
1832 | + </returns> | |
1833 | + </member> | |
1834 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.flush_pending"> | |
1835 | + <summary> | |
1836 | + Flush as much pending output as possible. All <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> output goes through this function so some applications may wish to | |
1837 | + modify it to avoid allocating a large <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> buffer and copying into it. | |
1838 | + </summary> | |
1839 | + <seealso cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.read_buf(System.Byte[],System.Int32,System.Int32)"/> | |
1840 | + </member> | |
1841 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.read_buf(System.Byte[],System.Int32,System.Int32)"> | |
1842 | + <summary> | |
1843 | + Read a new buffer from the current input stream, update the adler32 and total number of bytes read. All <see cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.deflate(ComponentAce.Compression.Libs.ZLib.FlushStrategy)"/> input goes | |
1844 | + through this function so some applications may wish to modify it to avoid allocating a large <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"/> buffer and copying from it. | |
1845 | + </summary> | |
1846 | + <seealso cref="M:ComponentAce.Compression.Libs.ZLib.ZStream.flush_pending"/> | |
1847 | + </member> | |
1848 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStream.free"> | |
1849 | + <summary> | |
1850 | + Frees all inner <see cref="T:ComponentAce.Compression.Libs.ZLib.ZStream"/> buffers. | |
1851 | + </summary> | |
1852 | + </member> | |
1853 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.adler"> | |
1854 | + <summary> | |
1855 | + Adler-32 value for uncompressed data processed so far. | |
1856 | + </summary> | |
1857 | + </member> | |
1858 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.Data_type"> | |
1859 | + <summary> | |
1860 | + Best guess about the data type: ascii or binary | |
1861 | + </summary> | |
1862 | + </member> | |
1863 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in"> | |
1864 | + <summary> | |
1865 | + Gets/Sets the next input byte array. | |
1866 | + </summary> | |
1867 | + </member> | |
1868 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in_index"> | |
1869 | + <summary> | |
1870 | + Index of the first byte in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in">input array</see>. | |
1871 | + </summary> | |
1872 | + </member> | |
1873 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_in"> | |
1874 | + <summary> | |
1875 | + Gets/Sets the number of bytes available in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in">input buffer</see>. | |
1876 | + </summary> | |
1877 | + </member> | |
1878 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.total_in"> | |
1879 | + <summary> | |
1880 | + Gets/Sets the total number of bytes in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_in">input buffer</see>. | |
1881 | + </summary> | |
1882 | + </member> | |
1883 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"> | |
1884 | + <summary> | |
1885 | + Gets/Sets the buffer for the next output data. | |
1886 | + </summary> | |
1887 | + </member> | |
1888 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out_index"> | |
1889 | + <summary> | |
1890 | + Gets/Sets the index of the first byte in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> byte array to write to. | |
1891 | + </summary> | |
1892 | + </member> | |
1893 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.avail_out"> | |
1894 | + <summary> | |
1895 | + Gets/Sets the remaining free space in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out"/> buffer. | |
1896 | + </summary> | |
1897 | + </member> | |
1898 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.total_out"> | |
1899 | + <summary> | |
1900 | + Gets/Sets the total number of bytes in the <see cref="P:ComponentAce.Compression.Libs.ZLib.ZStream.next_out">output array</see>. | |
1901 | + </summary> | |
1902 | + </member> | |
1903 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.msg"> | |
1904 | + <summary> | |
1905 | + Gets sets the last error message occurred during class operations. | |
1906 | + </summary> | |
1907 | + </member> | |
1908 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.dstate"> | |
1909 | + <summary> | |
1910 | + A deflate object to perform data compression | |
1911 | + </summary> | |
1912 | + </member> | |
1913 | + <member name="P:ComponentAce.Compression.Libs.ZLib.ZStream.istate"> | |
1914 | + <summary> | |
1915 | + Inflate object to perform data decompression | |
1916 | + </summary> | |
1917 | + </member> | |
1918 | + <member name="T:ComponentAce.Compression.Libs.ZLib.ZStreamException"> | |
1919 | + <summary> | |
1920 | + Exceptions that occur in ZStream | |
1921 | + </summary> | |
1922 | + </member> | |
1923 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStreamException.#ctor"> | |
1924 | + <summary> | |
1925 | + Default constructor. | |
1926 | + </summary> | |
1927 | + </member> | |
1928 | + <member name="M:ComponentAce.Compression.Libs.ZLib.ZStreamException.#ctor(System.String)"> | |
1929 | + <summary> | |
1930 | + Constructor which takes one parameter - an error message | |
1931 | + </summary> | |
1932 | + </member> | |
7 | 1933 | <member name="M:IronPython.Modules.PythonCodecs.charmap_build(System.String)"> |
8 | 1934 | <summary> |
9 | 1935 | Creates an optimized encoding mapping that can be consumed by an optimized version of charmap_encode. |
@@ -0,0 +1,4 @@ | ||
1 | + | |
2 | +import webbrowser | |
3 | + | |
4 | +webbrowser.open("http://xkcd.com/353/") |
@@ -1,82 +0,0 @@ | ||
1 | -import unittest | |
2 | -import sys | |
3 | -from ctypes import * | |
4 | -from ctypes.util import find_library | |
5 | -from ctypes.test import is_resource_enabled | |
6 | - | |
7 | -if sys.platform == "win32": | |
8 | - lib_gl = find_library("OpenGL32") | |
9 | - lib_glu = find_library("Glu32") | |
10 | - lib_gle = None | |
11 | -elif sys.platform == "darwin": | |
12 | - lib_gl = lib_glu = find_library("OpenGL") | |
13 | - lib_gle = None | |
14 | -else: | |
15 | - lib_gl = find_library("GL") | |
16 | - lib_glu = find_library("GLU") | |
17 | - lib_gle = find_library("gle") | |
18 | - | |
19 | -## print, for debugging | |
20 | -if is_resource_enabled("printing"): | |
21 | - if lib_gl or lib_glu or lib_gle: | |
22 | - print "OpenGL libraries:" | |
23 | - for item in (("GL", lib_gl), | |
24 | - ("GLU", lib_glu), | |
25 | - ("gle", lib_gle)): | |
26 | - print "\t", item | |
27 | - | |
28 | - | |
29 | -# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. | |
30 | -class Test_OpenGL_libs(unittest.TestCase): | |
31 | - def setUp(self): | |
32 | - self.gl = self.glu = self.gle = None | |
33 | - if lib_gl: | |
34 | - self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) | |
35 | - if lib_glu: | |
36 | - self.glu = CDLL(lib_glu, RTLD_GLOBAL) | |
37 | - if lib_gle: | |
38 | - try: | |
39 | - self.gle = CDLL(lib_gle) | |
40 | - except OSError: | |
41 | - pass | |
42 | - | |
43 | - if lib_gl: | |
44 | - def test_gl(self): | |
45 | - if self.gl: | |
46 | - self.gl.glClearIndex | |
47 | - | |
48 | - if lib_glu: | |
49 | - def test_glu(self): | |
50 | - if self.glu: | |
51 | - self.glu.gluBeginCurve | |
52 | - | |
53 | - if lib_gle: | |
54 | - def test_gle(self): | |
55 | - if self.gle: | |
56 | - self.gle.gleGetJoinStyle | |
57 | - | |
58 | -##if os.name == "posix" and sys.platform != "darwin": | |
59 | - | |
60 | -## # On platforms where the default shared library suffix is '.so', | |
61 | -## # at least some libraries can be loaded as attributes of the cdll | |
62 | -## # object, since ctypes now tries loading the lib again | |
63 | -## # with '.so' appended of the first try fails. | |
64 | -## # | |
65 | -## # Won't work for libc, unfortunately. OTOH, it isn't | |
66 | -## # needed for libc since this is already mapped into the current | |
67 | -## # process (?) | |
68 | -## # | |
69 | -## # On MAC OSX, it won't work either, because dlopen() needs a full path, | |
70 | -## # and the default suffix is either none or '.dylib'. | |
71 | - | |
72 | -## class LoadLibs(unittest.TestCase): | |
73 | -## def test_libm(self): | |
74 | -## import math | |
75 | -## libm = cdll.libm | |
76 | -## sqrt = libm.sqrt | |
77 | -## sqrt.argtypes = (c_double,) | |
78 | -## sqrt.restype = c_double | |
79 | -## self.assertEqual(sqrt(2), math.sqrt(2)) | |
80 | - | |
81 | -if __name__ == "__main__": | |
82 | - unittest.main() |
@@ -1,106 +0,0 @@ | ||
1 | -from ctypes import * | |
2 | -import sys, unittest | |
3 | -import os | |
4 | -from ctypes.util import find_library | |
5 | -from ctypes.test import is_resource_enabled | |
6 | - | |
7 | -libc_name = None | |
8 | -if os.name == "nt": | |
9 | - libc_name = find_library("c") | |
10 | -elif os.name == "ce": | |
11 | - libc_name = "coredll" | |
12 | -elif sys.platform == "cygwin": | |
13 | - libc_name = "cygwin1.dll" | |
14 | -else: | |
15 | - libc_name = find_library("c") | |
16 | - | |
17 | -if is_resource_enabled("printing"): | |
18 | - print "libc_name is", libc_name | |
19 | - | |
20 | -class LoaderTest(unittest.TestCase): | |
21 | - | |
22 | - unknowndll = "xxrandomnamexx" | |
23 | - | |
24 | - if libc_name is not None: | |
25 | - def test_load(self): | |
26 | - CDLL(libc_name) | |
27 | - CDLL(os.path.basename(libc_name)) | |
28 | - self.assertRaises(OSError, CDLL, self.unknowndll) | |
29 | - | |
30 | - if libc_name is not None and os.path.basename(libc_name) == "libc.so.6": | |
31 | - def test_load_version(self): | |
32 | - cdll.LoadLibrary("libc.so.6") | |
33 | - # linux uses version, libc 9 should not exist | |
34 | - self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") | |
35 | - self.assertRaises(OSError, cdll.LoadLibrary, self.unknowndll) | |
36 | - | |
37 | - def test_find(self): | |
38 | - for name in ("c", "m"): | |
39 | - lib = find_library(name) | |
40 | - if lib: | |
41 | - cdll.LoadLibrary(lib) | |
42 | - CDLL(lib) | |
43 | - | |
44 | - if os.name in ("nt", "ce"): | |
45 | - def test_load_library(self): | |
46 | - self.assertFalse(libc_name is None) | |
47 | - if is_resource_enabled("printing"): | |
48 | - print find_library("kernel32") | |
49 | - print find_library("user32") | |
50 | - | |
51 | - if os.name == "nt": | |
52 | - windll.kernel32.GetModuleHandleW | |
53 | - windll["kernel32"].GetModuleHandleW | |
54 | - windll.LoadLibrary("kernel32").GetModuleHandleW | |
55 | - WinDLL("kernel32").GetModuleHandleW | |
56 | - elif os.name == "ce": | |
57 | - windll.coredll.GetModuleHandleW | |
58 | - windll["coredll"].GetModuleHandleW | |
59 | - windll.LoadLibrary("coredll").GetModuleHandleW | |
60 | - WinDLL("coredll").GetModuleHandleW | |
61 | - | |
62 | - def test_load_ordinal_functions(self): | |
63 | - import _ctypes_test | |
64 | - dll = WinDLL(_ctypes_test.__file__) | |
65 | - # We load the same function both via ordinal and name | |
66 | - func_ord = dll[2] | |
67 | - func_name = dll.GetString | |
68 | - # addressof gets the address where the function pointer is stored | |
69 | - a_ord = addressof(func_ord) | |
70 | - a_name = addressof(func_name) | |
71 | - f_ord_addr = c_void_p.from_address(a_ord).value | |
72 | - f_name_addr = c_void_p.from_address(a_name).value | |
73 | - self.assertEqual(hex(f_ord_addr), hex(f_name_addr)) | |
74 | - | |
75 | - self.assertRaises(AttributeError, dll.__getitem__, 1234) | |
76 | - | |
77 | - if os.name == "nt": | |
78 | - def test_1703286_A(self): | |
79 | - from _ctypes import LoadLibrary, FreeLibrary | |
80 | - # On winXP 64-bit, advapi32 loads at an address that does | |
81 | - # NOT fit into a 32-bit integer. FreeLibrary must be able | |
82 | - # to accept this address. | |
83 | - | |
84 | - # These are tests for http://www.python.org/sf/1703286 | |
85 | - handle = LoadLibrary("advapi32") | |
86 | - FreeLibrary(handle) | |
87 | - | |
88 | - def test_1703286_B(self): | |
89 | - # Since on winXP 64-bit advapi32 loads like described | |
90 | - # above, the (arbitrarily selected) CloseEventLog function | |
91 | - # also has a high address. 'call_function' should accept | |
92 | - # addresses so large. | |
93 | - from _ctypes import call_function | |
94 | - advapi32 = windll.advapi32 | |
95 | - # Calling CloseEventLog with a NULL argument should fail, | |
96 | - # but the call should not segfault or so. | |
97 | - self.assertEqual(0, advapi32.CloseEventLog(None)) | |
98 | - windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p | |
99 | - windll.kernel32.GetProcAddress.restype = c_void_p | |
100 | - proc = windll.kernel32.GetProcAddress(advapi32._handle, "CloseEventLog") | |
101 | - self.assertTrue(proc) | |
102 | - # This is the real test: call the function via 'call_function' | |
103 | - self.assertEqual(0, call_function(proc, (None,))) | |
104 | - | |
105 | -if __name__ == "__main__": | |
106 | - unittest.main() |
@@ -1,93 +0,0 @@ | ||
1 | -from ctypes import * | |
2 | -import unittest, sys | |
3 | -from ctypes.test import is_resource_enabled | |
4 | -from test import test_support | |
5 | - | |
6 | -if not test_support.due_to_ironpython_bug("http://www.codeplex.com/IronPython/WorkItem/View.aspx?WorkItemId=22393"): | |
7 | - | |
8 | - ################################################################ | |
9 | - # This section should be moved into ctypes\__init__.py, when it's ready. | |
10 | - | |
11 | - from _ctypes import PyObj_FromPtr | |
12 | - | |
13 | - ################################################################ | |
14 | - | |
15 | - from sys import getrefcount as grc | |
16 | - if sys.version_info > (2, 4): | |
17 | - c_py_ssize_t = c_size_t | |
18 | - else: | |
19 | - c_py_ssize_t = c_int | |
20 | - | |
21 | - class PythonAPITestCase(unittest.TestCase): | |
22 | - | |
23 | - def test_PyString_FromStringAndSize(self): | |
24 | - PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize | |
25 | - | |
26 | - PyString_FromStringAndSize.restype = py_object | |
27 | - PyString_FromStringAndSize.argtypes = c_char_p, c_py_ssize_t | |
28 | - | |
29 | - self.assertEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc") | |
30 | - | |
31 | - def test_PyString_FromString(self): | |
32 | - pythonapi.PyString_FromString.restype = py_object | |
33 | - pythonapi.PyString_FromString.argtypes = (c_char_p,) | |
34 | - | |
35 | - s = "abc" | |
36 | - refcnt = grc(s) | |
37 | - pyob = pythonapi.PyString_FromString(s) | |
38 | - self.assertEqual(grc(s), refcnt) | |
39 | - self.assertEqual(s, pyob) | |
40 | - del pyob | |
41 | - self.assertEqual(grc(s), refcnt) | |
42 | - | |
43 | - if is_resource_enabled("refcount"): | |
44 | - # This test is unreliable, because it is possible that code in | |
45 | - # unittest changes the refcount of the '42' integer. So, it | |
46 | - # is disabled by default. | |
47 | - def test_PyInt_Long(self): | |
48 | - ref42 = grc(42) | |
49 | - pythonapi.PyInt_FromLong.restype = py_object | |
50 | - self.assertEqual(pythonapi.PyInt_FromLong(42), 42) | |
51 | - | |
52 | - self.assertEqual(grc(42), ref42) | |
53 | - | |
54 | - pythonapi.PyInt_AsLong.argtypes = (py_object,) | |
55 | - pythonapi.PyInt_AsLong.restype = c_long | |
56 | - | |
57 | - res = pythonapi.PyInt_AsLong(42) | |
58 | - self.assertEqual(grc(res), ref42 + 1) | |
59 | - del res | |
60 | - self.assertEqual(grc(42), ref42) | |
61 | - | |
62 | - def test_PyObj_FromPtr(self): | |
63 | - s = "abc def ghi jkl" | |
64 | - ref = grc(s) | |
65 | - # id(python-object) is the address | |
66 | - pyobj = PyObj_FromPtr(id(s)) | |
67 | - self.assertTrue(s is pyobj) | |
68 | - | |
69 | - self.assertEqual(grc(s), ref + 1) | |
70 | - del pyobj | |
71 | - self.assertEqual(grc(s), ref) | |
72 | - | |
73 | - def test_PyOS_snprintf(self): | |
74 | - PyOS_snprintf = pythonapi.PyOS_snprintf | |
75 | - PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p | |
76 | - | |
77 | - buf = c_buffer(256) | |
78 | - PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes") | |
79 | - self.assertEqual(buf.value, "Hello from ctypes") | |
80 | - | |
81 | - PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes", 1, 2, 3) | |
82 | - self.assertEqual(buf.value, "Hello from ctypes") | |
83 | - | |
84 | - # not enough arguments | |
85 | - self.assertRaises(TypeError, PyOS_snprintf, buf) | |
86 | - | |
87 | - def test_pyobject_repr(self): | |
88 | - self.assertEqual(repr(py_object()), "py_object(<NULL>)") | |
89 | - self.assertEqual(repr(py_object(42)), "py_object(42)") | |
90 | - self.assertEqual(repr(py_object(object)), "py_object(%r)" % object) | |
91 | - | |
92 | -if __name__ == "__main__": | |
93 | - unittest.main() |
@@ -27,14 +27,14 @@ else: | ||
27 | 27 | self.assertEqual(wcslen(u"ab\u2070"), 3) |
28 | 28 | # string args are converted |
29 | 29 | self.assertEqual(wcslen("abc"), 3) |
30 | - self.assertRaises(ctypes.ArgumentError, wcslen, "ab�") | |
30 | ||
31 | 31 | |
32 | 32 | def test_ascii_replace(self): |
33 | 33 | ctypes.set_conversion_mode("ascii", "replace") |
34 | 34 | self.assertEqual(wcslen(u"abc"), 3) |
35 | 35 | self.assertEqual(wcslen(u"ab\u2070"), 3) |
36 | 36 | self.assertEqual(wcslen("abc"), 3) |
37 | - self.assertEqual(wcslen("ab�"), 3) | |
37 | ||
38 | 38 | |
39 | 39 | def test_ascii_ignore(self): |
40 | 40 | ctypes.set_conversion_mode("ascii", "ignore") |
@@ -42,14 +42,14 @@ else: | ||
42 | 42 | self.assertEqual(wcslen(u"ab\u2070"), 3) |
43 | 43 | # ignore error mode skips non-ascii characters |
44 | 44 | self.assertEqual(wcslen("abc"), 3) |
45 | - self.assertEqual(wcslen("����"), 0) | |
45 | + self.assertEqual(wcslen("糜?"), 0) | |
46 | 46 | |
47 | 47 | def test_latin1_strict(self): |
48 | 48 | ctypes.set_conversion_mode("latin-1", "strict") |
49 | 49 | self.assertEqual(wcslen(u"abc"), 3) |
50 | 50 | self.assertEqual(wcslen(u"ab\u2070"), 3) |
51 | 51 | self.assertEqual(wcslen("abc"), 3) |
52 | - self.assertEqual(wcslen("����"), 4) | |
52 | + self.assertEqual(wcslen("糜?"), 4) | |
53 | 53 | |
54 | 54 | def test_buffers(self): |
55 | 55 | ctypes.set_conversion_mode("ascii", "strict") |
@@ -57,7 +57,7 @@ else: | ||
57 | 57 | self.assertEqual(len(buf), 3+1) |
58 | 58 | |
59 | 59 | ctypes.set_conversion_mode("ascii", "replace") |
60 | - buf = ctypes.create_unicode_buffer("ab���") | |
60 | + buf = ctypes.create_unicode_buffer("ab糜?) | |
61 | 61 | self.assertEqual(buf[:], u"ab\uFFFD\uFFFD\uFFFD\0") |
62 | 62 | self.assertEqual(buf[::], u"ab\uFFFD\uFFFD\uFFFD\0") |
63 | 63 | self.assertEqual(buf[::-1], u"\0\uFFFD\uFFFD\uFFFDba") |
@@ -65,7 +65,7 @@ else: | ||
65 | 65 | self.assertEqual(buf[6:5:-1], u"") |
66 | 66 | |
67 | 67 | ctypes.set_conversion_mode("ascii", "ignore") |
68 | - buf = ctypes.create_unicode_buffer("ab���") | |
68 | + buf = ctypes.create_unicode_buffer("ab糜?) | |
69 | 69 | # is that correct? not sure. But with 'ignore', you get what you pay for.. |
70 | 70 | self.assertEqual(buf[:], u"ab\0\0\0\0") |
71 | 71 | self.assertEqual(buf[::], u"ab\0\0\0\0") |
@@ -91,19 +91,19 @@ else: | ||
91 | 91 | ctypes.set_conversion_mode("ascii", "strict") |
92 | 92 | self.assertEqual(func("abc"), "abc") |
93 | 93 | self.assertEqual(func(u"abc"), "abc") |
94 | - self.assertRaises(ctypes.ArgumentError, func, u"ab�") | |
94 | ||
95 | 95 | |
96 | 96 | def test_ascii_ignore(self): |
97 | 97 | ctypes.set_conversion_mode("ascii", "ignore") |
98 | 98 | self.assertEqual(func("abc"), "abc") |
99 | 99 | self.assertEqual(func(u"abc"), "abc") |
100 | - self.assertEqual(func(u"����"), "") | |
100 | + self.assertEqual(func(u"糜?"), "") | |
101 | 101 | |
102 | 102 | def test_ascii_replace(self): |
103 | 103 | ctypes.set_conversion_mode("ascii", "replace") |
104 | 104 | self.assertEqual(func("abc"), "abc") |
105 | 105 | self.assertEqual(func(u"abc"), "abc") |
106 | - self.assertEqual(func(u"����"), "????") | |
106 | + self.assertEqual(func(u"糜?"), "????") | |
107 | 107 | |
108 | 108 | def test_buffers(self): |
109 | 109 | ctypes.set_conversion_mode("ascii", "strict") |
@@ -111,7 +111,7 @@ else: | ||
111 | 111 | self.assertEqual(len(buf), 3+1) |
112 | 112 | |
113 | 113 | ctypes.set_conversion_mode("ascii", "replace") |
114 | - buf = ctypes.create_string_buffer(u"ab���") | |
114 | + buf = ctypes.create_string_buffer(u"ab糜?) | |
115 | 115 | self.assertEqual(buf[:], "ab???\0") |
116 | 116 | self.assertEqual(buf[::], "ab???\0") |
117 | 117 | self.assertEqual(buf[::-1], "\0???ba") |
@@ -119,7 +119,7 @@ else: | ||
119 | 119 | self.assertEqual(buf[6:5:-1], "") |
120 | 120 | |
121 | 121 | ctypes.set_conversion_mode("ascii", "ignore") |
122 | - buf = ctypes.create_string_buffer(u"ab���") | |
122 | + buf = ctypes.create_string_buffer(u"ab糜?) | |
123 | 123 | # is that correct? not sure. But with 'ignore', you get what you pay for.. |
124 | 124 | self.assertEqual(buf[:], "ab\0\0\0\0") |
125 | 125 | self.assertEqual(buf[::], "ab\0\0\0\0") |
@@ -1,7 +1,7 @@ | ||
1 | 1 | # -*- coding: iso-8859-1 -*- |
2 | 2 | """ Codec for the Punicode encoding, as specified in RFC 3492 |
3 | 3 | |
4 | -Written by Martin v. L�wis. | |
4 | +Written by Martin v. L?is. | |
5 | 5 | """ |
6 | 6 | |
7 | 7 | import codecs |
@@ -2,7 +2,7 @@ | ||
2 | 2 | """ Python 'escape' Codec |
3 | 3 | |
4 | 4 | |
5 | -Written by Martin v. L�wis (martin@v.loewis.de). | |
5 | +Written by Martin v. L?is (martin@v.loewis.de). | |
6 | 6 | |
7 | 7 | """ |
8 | 8 | import codecs |
@@ -0,0 +1,102 @@ | ||
1 | +""" Python 'zlib_codec' Codec - zlib compression encoding | |
2 | + | |
3 | + Unlike most of the other codecs which target Unicode, this codec | |
4 | + will return Python string objects for both encode and decode. | |
5 | + | |
6 | + Written by Marc-Andre Lemburg (mal@lemburg.com). | |
7 | + | |
8 | +""" | |
9 | +import codecs | |
10 | +import zlib # this codec needs the optional zlib module ! | |
11 | + | |
12 | +### Codec APIs | |
13 | + | |
14 | +def zlib_encode(input,errors='strict'): | |
15 | + | |
16 | + """ Encodes the object input and returns a tuple (output | |
17 | + object, length consumed). | |
18 | + | |
19 | + errors defines the error handling to apply. It defaults to | |
20 | + 'strict' handling which is the only currently supported | |
21 | + error handling for this codec. | |
22 | + | |
23 | + """ | |
24 | + assert errors == 'strict' | |
25 | + output = zlib.compress(input) | |
26 | + return (output, len(input)) | |
27 | + | |
28 | +def zlib_decode(input,errors='strict'): | |
29 | + | |
30 | + """ Decodes the object input and returns a tuple (output | |
31 | + object, length consumed). | |
32 | + | |
33 | + input must be an object which provides the bf_getreadbuf | |
34 | + buffer slot. Python strings, buffer objects and memory | |
35 | + mapped files are examples of objects providing this slot. | |
36 | + | |
37 | + errors defines the error handling to apply. It defaults to | |
38 | + 'strict' handling which is the only currently supported | |
39 | + error handling for this codec. | |
40 | + | |
41 | + """ | |
42 | + assert errors == 'strict' | |
43 | + output = zlib.decompress(input) | |
44 | + return (output, len(input)) | |
45 | + | |
46 | +class Codec(codecs.Codec): | |
47 | + | |
48 | + def encode(self, input, errors='strict'): | |
49 | + return zlib_encode(input, errors) | |
50 | + def decode(self, input, errors='strict'): | |
51 | + return zlib_decode(input, errors) | |
52 | + | |
53 | +class IncrementalEncoder(codecs.IncrementalEncoder): | |
54 | + def __init__(self, errors='strict'): | |
55 | + assert errors == 'strict' | |
56 | + self.errors = errors | |
57 | + self.compressobj = zlib.compressobj() | |
58 | + | |
59 | + def encode(self, input, final=False): | |
60 | + if final: | |
61 | + c = self.compressobj.compress(input) | |
62 | + return c + self.compressobj.flush() | |
63 | + else: | |
64 | + return self.compressobj.compress(input) | |
65 | + | |
66 | + def reset(self): | |
67 | + self.compressobj = zlib.compressobj() | |
68 | + | |
69 | +class IncrementalDecoder(codecs.IncrementalDecoder): | |
70 | + def __init__(self, errors='strict'): | |
71 | + assert errors == 'strict' | |
72 | + self.errors = errors | |
73 | + self.decompressobj = zlib.decompressobj() | |
74 | + | |
75 | + def decode(self, input, final=False): | |
76 | + if final: | |
77 | + c = self.decompressobj.decompress(input) | |
78 | + return c + self.decompressobj.flush() | |
79 | + else: | |
80 | + return self.decompressobj.decompress(input) | |
81 | + | |
82 | + def reset(self): | |
83 | + self.decompressobj = zlib.decompressobj() | |
84 | + | |
85 | +class StreamWriter(Codec,codecs.StreamWriter): | |
86 | + pass | |
87 | + | |
88 | +class StreamReader(Codec,codecs.StreamReader): | |
89 | + pass | |
90 | + | |
91 | +### encodings module API | |
92 | + | |
93 | +def getregentry(): | |
94 | + return codecs.CodecInfo( | |
95 | + name='zlib', | |
96 | + encode=zlib_encode, | |
97 | + decode=zlib_decode, | |
98 | + incrementalencoder=IncrementalEncoder, | |
99 | + incrementaldecoder=IncrementalDecoder, | |
100 | + streamreader=StreamReader, | |
101 | + streamwriter=StreamWriter, | |
102 | + ) |
@@ -0,0 +1,499 @@ | ||
1 | +"""Functions that read and write gzipped files. | |
2 | + | |
3 | +The user of the file doesn't have to worry about the compression, | |
4 | +but random access is not allowed.""" | |
5 | + | |
6 | +# based on Andrew Kuchling's minigzip.py distributed with the zlib module | |
7 | + | |
8 | +import struct, sys, time, os | |
9 | +import zlib | |
10 | +import io | |
11 | +import __builtin__ | |
12 | + | |
13 | +__all__ = ["GzipFile","open"] | |
14 | + | |
15 | +FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 | |
16 | + | |
17 | +READ, WRITE = 1, 2 | |
18 | + | |
19 | +def write32u(output, value): | |
20 | + # The L format writes the bit pattern correctly whether signed | |
21 | + # or unsigned. | |
22 | + output.write(struct.pack("<L", value)) | |
23 | + | |
24 | +def read32(input): | |
25 | + return struct.unpack("<I", input.read(4))[0] | |
26 | + | |
27 | +def open(filename, mode="rb", compresslevel=9): | |
28 | + """Shorthand for GzipFile(filename, mode, compresslevel). | |
29 | + | |
30 | + The filename argument is required; mode defaults to 'rb' | |
31 | + and compresslevel defaults to 9. | |
32 | + | |
33 | + """ | |
34 | + return GzipFile(filename, mode, compresslevel) | |
35 | + | |
36 | +class GzipFile(io.BufferedIOBase): | |
37 | + """The GzipFile class simulates most of the methods of a file object with | |
38 | + the exception of the readinto() and truncate() methods. | |
39 | + | |
40 | + """ | |
41 | + | |
42 | + myfileobj = None | |
43 | + max_read_chunk = 10 * 1024 * 1024 # 10Mb | |
44 | + | |
45 | + def __init__(self, filename=None, mode=None, | |
46 | + compresslevel=9, fileobj=None, mtime=None): | |
47 | + """Constructor for the GzipFile class. | |
48 | + | |
49 | + At least one of fileobj and filename must be given a | |
50 | + non-trivial value. | |
51 | + | |
52 | + The new class instance is based on fileobj, which can be a regular | |
53 | + file, a StringIO object, or any other object which simulates a file. | |
54 | + It defaults to None, in which case filename is opened to provide | |
55 | + a file object. | |
56 | + | |
57 | + When fileobj is not None, the filename argument is only used to be | |
58 | + included in the gzip file header, which may includes the original | |
59 | + filename of the uncompressed file. It defaults to the filename of | |
60 | + fileobj, if discernible; otherwise, it defaults to the empty string, | |
61 | + and in this case the original filename is not included in the header. | |
62 | + | |
63 | + The mode argument can be any of 'r', 'rb', 'a', 'ab', 'w', or 'wb', | |
64 | + depending on whether the file will be read or written. The default | |
65 | + is the mode of fileobj if discernible; otherwise, the default is 'rb'. | |
66 | + Be aware that only the 'rb', 'ab', and 'wb' values should be used | |
67 | + for cross-platform portability. | |
68 | + | |
69 | + The compresslevel argument is an integer from 1 to 9 controlling the | |
70 | + level of compression; 1 is fastest and produces the least compression, | |
71 | + and 9 is slowest and produces the most compression. The default is 9. | |
72 | + | |
73 | + The mtime argument is an optional numeric timestamp to be written | |
74 | + to the stream when compressing. All gzip compressed streams | |
75 | + are required to contain a timestamp. If omitted or None, the | |
76 | + current time is used. This module ignores the timestamp when | |
77 | + decompressing; however, some programs, such as gunzip, make use | |
78 | + of it. The format of the timestamp is the same as that of the | |
79 | + return value of time.time() and of the st_mtime member of the | |
80 | + object returned by os.stat(). | |
81 | + | |
82 | + """ | |
83 | + | |
84 | + # guarantee the file is opened in binary mode on platforms | |
85 | + # that care about that sort of thing | |
86 | + if mode and 'b' not in mode: | |
87 | + mode += 'b' | |
88 | + if fileobj is None: | |
89 | + fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb') | |
90 | + if filename is None: | |
91 | + if hasattr(fileobj, 'name'): filename = fileobj.name | |
92 | + else: filename = '' | |
93 | + if mode is None: | |
94 | + if hasattr(fileobj, 'mode'): mode = fileobj.mode | |
95 | + else: mode = 'rb' | |
96 | + | |
97 | + if mode[0:1] == 'r': | |
98 | + self.mode = READ | |
99 | + # Set flag indicating start of a new member | |
100 | + self._new_member = True | |
101 | + # Buffer data read from gzip file. extrastart is offset in | |
102 | + # stream where buffer starts. extrasize is number of | |
103 | + # bytes remaining in buffer from current stream position. | |
104 | + self.extrabuf = "" | |
105 | + self.extrasize = 0 | |
106 | + self.extrastart = 0 | |
107 | + self.name = filename | |
108 | + # Starts small, scales exponentially | |
109 | + self.min_readsize = 100 | |
110 | + | |
111 | + elif mode[0:1] == 'w' or mode[0:1] == 'a': | |
112 | + self.mode = WRITE | |
113 | + self._init_write(filename) | |
114 | + self.compress = zlib.compressobj(compresslevel, | |
115 | + zlib.DEFLATED, | |
116 | + -zlib.MAX_WBITS, | |
117 | + zlib.DEF_MEM_LEVEL, | |
118 | + 0) | |
119 | + else: | |
120 | + raise IOError, "Mode " + mode + " not supported" | |
121 | + | |
122 | + self.fileobj = fileobj | |
123 | + self.offset = 0 | |
124 | + self.mtime = mtime | |
125 | + | |
126 | + if self.mode == WRITE: | |
127 | + self._write_gzip_header() | |
128 | + | |
129 | + @property | |
130 | + def filename(self): | |
131 | + import warnings | |
132 | + warnings.warn("use the name attribute", DeprecationWarning, 2) | |
133 | + if self.mode == WRITE and self.name[-3:] != ".gz": | |
134 | + return self.name + ".gz" | |
135 | + return self.name | |
136 | + | |
137 | + def __repr__(self): | |
138 | + s = repr(self.fileobj) | |
139 | + return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>' | |
140 | + | |
141 | + def _init_write(self, filename): | |
142 | + self.name = filename | |
143 | + self.crc = zlib.crc32("") & 0xffffffffL | |
144 | + self.size = 0 | |
145 | + self.writebuf = [] | |
146 | + self.bufsize = 0 | |
147 | + | |
148 | + def _write_gzip_header(self): | |
149 | + self.fileobj.write('\037\213') # magic header | |
150 | + self.fileobj.write('\010') # compression method | |
151 | + fname = os.path.basename(self.name) | |
152 | + if fname.endswith(".gz"): | |
153 | + fname = fname[:-3] | |
154 | + flags = 0 | |
155 | + if fname: | |
156 | + flags = FNAME | |
157 | + self.fileobj.write(chr(flags)) | |
158 | + mtime = self.mtime | |
159 | + if mtime is None: | |
160 | + mtime = time.time() | |
161 | + write32u(self.fileobj, long(mtime)) | |
162 | + self.fileobj.write('\002') | |
163 | + self.fileobj.write('\377') | |
164 | + if fname: | |
165 | + self.fileobj.write(fname + '\000') | |
166 | + | |
167 | + def _init_read(self): | |
168 | + self.crc = zlib.crc32("") & 0xffffffffL | |
169 | + self.size = 0 | |
170 | + | |
171 | + def _read_gzip_header(self): | |
172 | + magic = self.fileobj.read(2) | |
173 | + if magic != '\037\213': | |
174 | + raise IOError, 'Not a gzipped file' | |
175 | + method = ord( self.fileobj.read(1) ) | |
176 | + if method != 8: | |
177 | + raise IOError, 'Unknown compression method' | |
178 | + flag = ord( self.fileobj.read(1) ) | |
179 | + self.mtime = read32(self.fileobj) | |
180 | + # extraflag = self.fileobj.read(1) | |
181 | + # os = self.fileobj.read(1) | |
182 | + self.fileobj.read(2) | |
183 | + | |
184 | + if flag & FEXTRA: | |
185 | + # Read & discard the extra field, if present | |
186 | + xlen = ord(self.fileobj.read(1)) | |
187 | + xlen = xlen + 256*ord(self.fileobj.read(1)) | |
188 | + self.fileobj.read(xlen) | |
189 | + if flag & FNAME: | |
190 | + # Read and discard a null-terminated string containing the filename | |
191 | + while True: | |
192 | + s = self.fileobj.read(1) | |
193 | + if not s or s=='\000': | |
194 | + break | |
195 | + if flag & FCOMMENT: | |
196 | + # Read and discard a null-terminated string containing a comment | |
197 | + while True: | |
198 | + s = self.fileobj.read(1) | |
199 | + if not s or s=='\000': | |
200 | + break | |
201 | + if flag & FHCRC: | |
202 | + self.fileobj.read(2) # Read & discard the 16-bit header CRC | |
203 | + | |
204 | + def write(self,data): | |
205 | + if self.mode != WRITE: | |
206 | + import errno | |
207 | + raise IOError(errno.EBADF, "write() on read-only GzipFile object") | |
208 | + | |
209 | + if self.fileobj is None: | |
210 | + raise ValueError, "write() on closed GzipFile object" | |
211 | + | |
212 | + # Convert data type if called by io.BufferedWriter. | |
213 | + if isinstance(data, memoryview): | |
214 | + data = data.tobytes() | |
215 | + | |
216 | + if len(data) > 0: | |
217 | + self.size = self.size + len(data) | |
218 | + self.crc = zlib.crc32(data, self.crc) & 0xffffffffL | |
219 | + self.fileobj.write( self.compress.compress(data) ) | |
220 | + self.offset += len(data) | |
221 | + | |
222 | + return len(data) | |
223 | + | |
224 | + def read(self, size=-1): | |
225 | + if self.mode != READ: | |
226 | + import errno | |
227 | + raise IOError(errno.EBADF, "read() on write-only GzipFile object") | |
228 | + | |
229 | + if self.extrasize <= 0 and self.fileobj is None: | |
230 | + return '' | |
231 | + | |
232 | + readsize = 1024 | |
233 | + if size < 0: # get the whole thing | |
234 | + try: | |
235 | + while True: | |
236 | + self._read(readsize) | |
237 | + readsize = min(self.max_read_chunk, readsize * 2) | |
238 | + except EOFError: | |
239 | + size = self.extrasize | |
240 | + else: # just get some more of it | |
241 | + try: | |
242 | + while size > self.extrasize: | |
243 | + self._read(readsize) | |
244 | + readsize = min(self.max_read_chunk, readsize * 2) | |
245 | + except EOFError: | |
246 | + if size > self.extrasize: | |
247 | + size = self.extrasize | |
248 | + | |
249 | + offset = self.offset - self.extrastart | |
250 | + chunk = self.extrabuf[offset: offset + size] | |
251 | + self.extrasize = self.extrasize - size | |
252 | + | |
253 | + self.offset += size | |
254 | + return chunk | |
255 | + | |
256 | + def _unread(self, buf): | |
257 | + self.extrasize = len(buf) + self.extrasize | |
258 | + self.offset -= len(buf) | |
259 | + | |
260 | + def _read(self, size=1024): | |
261 | + if self.fileobj is None: | |
262 | + raise EOFError, "Reached EOF" | |
263 | + | |
264 | + if self._new_member: | |
265 | + # If the _new_member flag is set, we have to | |
266 | + # jump to the next member, if there is one. | |
267 | + # | |
268 | + # First, check if we're at the end of the file; | |
269 | + # if so, it's time to stop; no more members to read. | |
270 | + pos = self.fileobj.tell() # Save current position | |
271 | + self.fileobj.seek(0, 2) # Seek to end of file | |
272 | + if pos == self.fileobj.tell(): | |
273 | + raise EOFError, "Reached EOF" | |
274 | + else: | |
275 | + self.fileobj.seek( pos ) # Return to original position | |
276 | + | |
277 | + self._init_read() | |
278 | + self._read_gzip_header() | |
279 | + self.decompress = zlib.decompressobj(-zlib.MAX_WBITS) | |
280 | + self._new_member = False | |
281 | + | |
282 | + # Read a chunk of data from the file | |
283 | + buf = self.fileobj.read(size) | |
284 | + | |
285 | + # If the EOF has been reached, flush the decompression object | |
286 | + # and mark this object as finished. | |
287 | + | |
288 | + if buf == "": | |
289 | + uncompress = self.decompress.flush() | |
290 | + self._read_eof() | |
291 | + self._add_read_data( uncompress ) | |
292 | + raise EOFError, 'Reached EOF' | |
293 | + | |
294 | + uncompress = self.decompress.decompress(buf) | |
295 | + self._add_read_data( uncompress ) | |
296 | + | |
297 | + if self.decompress.unused_data != "": | |
298 | + # Ending case: we've come to the end of a member in the file, | |
299 | + # so seek back to the start of the unused data, finish up | |
300 | + # this member, and read a new gzip header. | |
301 | + # (The number of bytes to seek back is the length of the unused | |
302 | + # data, minus 8 because _read_eof() will rewind a further 8 bytes) | |
303 | + self.fileobj.seek( -len(self.decompress.unused_data)+8, 1) | |
304 | + | |
305 | + # Check the CRC and file size, and set the flag so we read | |
306 | + # a new member on the next call | |
307 | + self._read_eof() | |
308 | + self._new_member = True | |
309 | + | |
310 | + def _add_read_data(self, data): | |
311 | + self.crc = zlib.crc32(data, self.crc) & 0xffffffffL | |
312 | + offset = self.offset - self.extrastart | |
313 | + self.extrabuf = self.extrabuf[offset:] + data | |
314 | + self.extrasize = self.extrasize + len(data) | |
315 | + self.extrastart = self.offset | |
316 | + self.size = self.size + len(data) | |
317 | + | |
318 | + def _read_eof(self): | |
319 | + # We've read to the end of the file, so we have to rewind in order | |
320 | + # to reread the 8 bytes containing the CRC and the file size. | |
321 | + # We check the that the computed CRC and size of the | |
322 | + # uncompressed data matches the stored values. Note that the size | |
323 | + # stored is the true file size mod 2**32. | |
324 | + self.fileobj.seek(-8, 1) | |
325 | + crc32 = read32(self.fileobj) | |
326 | + isize = read32(self.fileobj) # may exceed 2GB | |
327 | + if crc32 != self.crc: | |
328 | + raise IOError("CRC check failed %s != %s" % (hex(crc32), | |
329 | + hex(self.crc))) | |
330 | + elif isize != (self.size & 0xffffffffL): | |
331 | + raise IOError, "Incorrect length of data produced" | |
332 | + | |
333 | + # Gzip files can be padded with zeroes and still have archives. | |
334 | + # Consume all zero bytes and set the file position to the first | |
335 | + # non-zero byte. See http://www.gzip.org/#faq8 | |
336 | + c = "\x00" | |
337 | + while c == "\x00": | |
338 | + c = self.fileobj.read(1) | |
339 | + if c: | |
340 | + self.fileobj.seek(-1, 1) | |
341 | + | |
342 | + @property | |
343 | + def closed(self): | |
344 | + return self.fileobj is None | |
345 | + | |
346 | + def close(self): | |
347 | + if self.fileobj is None: | |
348 | + return | |
349 | + if self.mode == WRITE: | |
350 | + self.fileobj.write(self.compress.flush()) | |
351 | + write32u(self.fileobj, self.crc) | |
352 | + # self.size may exceed 2GB, or even 4GB | |
353 | + write32u(self.fileobj, self.size & 0xffffffffL) | |
354 | + self.fileobj = None | |
355 | + elif self.mode == READ: | |
356 | + self.fileobj = None | |
357 | + if self.myfileobj: | |
358 | + self.myfileobj.close() | |
359 | + self.myfileobj = None | |
360 | + | |
361 | + def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): | |
362 | + if self.mode == WRITE: | |
363 | + # Ensure the compressor's buffer is flushed | |
364 | + self.fileobj.write(self.compress.flush(zlib_mode)) | |
365 | + self.fileobj.flush() | |
366 | + | |
367 | + def fileno(self): | |
368 | + """Invoke the underlying file object's fileno() method. | |
369 | + | |
370 | + This will raise AttributeError if the underlying file object | |
371 | + doesn't support fileno(). | |
372 | + """ | |
373 | + return self.fileobj.fileno() | |
374 | + | |
375 | + def rewind(self): | |
376 | + '''Return the uncompressed stream file position indicator to the | |
377 | + beginning of the file''' | |
378 | + if self.mode != READ: | |
379 | + raise IOError("Can't rewind in write mode") | |
380 | + self.fileobj.seek(0) | |
381 | + self._new_member = True | |
382 | + self.extrabuf = "" | |
383 | + self.extrasize = 0 | |
384 | + self.extrastart = 0 | |
385 | + self.offset = 0 | |
386 | + | |
387 | + def readable(self): | |
388 | + return self.mode == READ | |
389 | + | |
390 | + def writable(self): | |
391 | + return self.mode == WRITE | |
392 | + | |
393 | + def seekable(self): | |
394 | + return True | |
395 | + | |
396 | + def seek(self, offset, whence=0): | |
397 | + if whence: | |
398 | + if whence == 1: | |
399 | + offset = self.offset + offset | |
400 | + else: | |
401 | + raise ValueError('Seek from end not supported') | |
402 | + if self.mode == WRITE: | |
403 | + if offset < self.offset: | |
404 | + raise IOError('Negative seek in write mode') | |
405 | + count = offset - self.offset | |
406 | + for i in range(count // 1024): | |
407 | + self.write(1024 * '\0') | |
408 | + self.write((count % 1024) * '\0') | |
409 | + elif self.mode == READ: | |
410 | + if offset < self.offset: | |
411 | + # for negative seek, rewind and do positive seek | |
412 | + self.rewind() | |
413 | + count = offset - self.offset | |
414 | + for i in range(count // 1024): | |
415 | + self.read(1024) | |
416 | + self.read(count % 1024) | |
417 | + | |
418 | + return self.offset | |
419 | + | |
420 | + def readline(self, size=-1): | |
421 | + if size < 0: | |
422 | + # Shortcut common case - newline found in buffer. | |
423 | + offset = self.offset - self.extrastart | |
424 | + i = self.extrabuf.find('\n', offset) + 1 | |
425 | + if i > 0: | |
426 | + self.extrasize -= i - offset | |
427 | + self.offset += i - offset | |
428 | + return self.extrabuf[offset: i] | |
429 | + | |
430 | + size = sys.maxint | |
431 | + readsize = self.min_readsize | |
432 | + else: | |
433 | + readsize = size | |
434 | + bufs = [] | |
435 | + while size != 0: | |
436 | + c = self.read(readsize) | |
437 | + i = c.find('\n') | |
438 | + | |
439 | + # We set i=size to break out of the loop under two | |
440 | + # conditions: 1) there's no newline, and the chunk is | |
441 | + # larger than size, or 2) there is a newline, but the | |
442 | + # resulting line would be longer than 'size'. | |
443 | + if (size <= i) or (i == -1 and len(c) > size): | |
444 | + i = size - 1 | |
445 | + | |
446 | + if i >= 0 or c == '': | |
447 | + bufs.append(c[:i + 1]) # Add portion of last chunk | |
448 | + self._unread(c[i + 1:]) # Push back rest of chunk | |
449 | + break | |
450 | + | |
451 | + # Append chunk to list, decrease 'size', | |
452 | + bufs.append(c) | |
453 | + size = size - len(c) | |
454 | + readsize = min(size, readsize * 2) | |
455 | + if readsize > self.min_readsize: | |
456 | + self.min_readsize = min(readsize, self.min_readsize * 2, 512) | |
457 | + return ''.join(bufs) # Return resulting line | |
458 | + | |
459 | + | |
460 | +def _test(): | |
461 | + # Act like gzip; with -d, act like gunzip. | |
462 | + # The input file is not deleted, however, nor are any other gzip | |
463 | + # options or features supported. | |
464 | + args = sys.argv[1:] | |
465 | + decompress = args and args[0] == "-d" | |
466 | + if decompress: | |
467 | + args = args[1:] | |
468 | + if not args: | |
469 | + args = ["-"] | |
470 | + for arg in args: | |
471 | + if decompress: | |
472 | + if arg == "-": | |
473 | + f = GzipFile(filename="", mode="rb", fileobj=sys.stdin) | |
474 | + g = sys.stdout | |
475 | + else: | |
476 | + if arg[-3:] != ".gz": | |
477 | + print "filename doesn't end in .gz:", repr(arg) | |
478 | + continue | |
479 | + f = open(arg, "rb") | |
480 | + g = __builtin__.open(arg[:-3], "wb") | |
481 | + else: | |
482 | + if arg == "-": | |
483 | + f = sys.stdin | |
484 | + g = GzipFile(filename="", mode="wb", fileobj=sys.stdout) | |
485 | + else: | |
486 | + f = __builtin__.open(arg, "rb") | |
487 | + g = open(arg + ".gz", "wb") | |
488 | + while True: | |
489 | + chunk = f.read(1024) | |
490 | + if not chunk: | |
491 | + break | |
492 | + g.write(chunk) | |
493 | + if g is not sys.stdout: | |
494 | + g.close() | |
495 | + if f is not sys.stdin: | |
496 | + f.close() | |
497 | + | |
498 | +if __name__ == '__main__': | |
499 | + _test() |
@@ -34,7 +34,7 @@ maintains the heap invariant! | ||
34 | 34 | |
35 | 35 | __about__ = """Heap queues |
36 | 36 | |
37 | -[explanation by Fran?スois Pinard] | |
37 | +[explanation by Fran輟is Pinard] | |
38 | 38 | |
39 | 39 | Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for |
40 | 40 | all k, counting elements from 0. For the sake of comparison, |
@@ -0,0 +1,1512 @@ | ||
1 | +"""IMAP4 client. | |
2 | + | |
3 | +Based on RFC 2060. | |
4 | + | |
5 | +Public class: IMAP4 | |
6 | +Public variable: Debug | |
7 | +Public functions: Internaldate2tuple | |
8 | + Int2AP | |
9 | + ParseFlags | |
10 | + Time2Internaldate | |
11 | +""" | |
12 | + | |
13 | +# Author: Piers Lauder <piers@cs.su.oz.au> December 1997. | |
14 | +# | |
15 | +# Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998. | |
16 | +# String method conversion by ESR, February 2001. | |
17 | +# GET/SETACL contributed by Anthony Baxter <anthony@interlink.com.au> April 2001. | |
18 | +# IMAP4_SSL contributed by Tino Lange <Tino.Lange@isg.de> March 2002. | |
19 | +# GET/SETQUOTA contributed by Andreas Zeidler <az@kreativkombinat.de> June 2002. | |
20 | +# PROXYAUTH contributed by Rick Holbert <holbert.13@osu.edu> November 2002. | |
21 | +# GET/SETANNOTATION contributed by Tomas Lindroos <skitta@abo.fi> June 2005. | |
22 | + | |
23 | +__version__ = "2.58" | |
24 | + | |
25 | +import binascii, random, re, socket, subprocess, sys, time | |
26 | + | |
27 | +__all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", | |
28 | + "Int2AP", "ParseFlags", "Time2Internaldate"] | |
29 | + | |
30 | +# Globals | |
31 | + | |
32 | +CRLF = '\r\n' | |
33 | +Debug = 0 | |
34 | +IMAP4_PORT = 143 | |
35 | +IMAP4_SSL_PORT = 993 | |
36 | +AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first | |
37 | + | |
38 | +# Commands | |
39 | + | |
40 | +Commands = { | |
41 | + # name valid states | |
42 | + 'APPEND': ('AUTH', 'SELECTED'), | |
43 | + 'AUTHENTICATE': ('NONAUTH',), | |
44 | + 'CAPABILITY': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), | |
45 | + 'CHECK': ('SELECTED',), | |
46 | + 'CLOSE': ('SELECTED',), | |
47 | + 'COPY': ('SELECTED',), | |
48 | + 'CREATE': ('AUTH', 'SELECTED'), | |
49 | + 'DELETE': ('AUTH', 'SELECTED'), | |
50 | + 'DELETEACL': ('AUTH', 'SELECTED'), | |
51 | + 'EXAMINE': ('AUTH', 'SELECTED'), | |
52 | + 'EXPUNGE': ('SELECTED',), | |
53 | + 'FETCH': ('SELECTED',), | |
54 | + 'GETACL': ('AUTH', 'SELECTED'), | |
55 | + 'GETANNOTATION':('AUTH', 'SELECTED'), | |
56 | + 'GETQUOTA': ('AUTH', 'SELECTED'), | |
57 | + 'GETQUOTAROOT': ('AUTH', 'SELECTED'), | |
58 | + 'MYRIGHTS': ('AUTH', 'SELECTED'), | |
59 | + 'LIST': ('AUTH', 'SELECTED'), | |
60 | + 'LOGIN': ('NONAUTH',), | |
61 | + 'LOGOUT': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), | |
62 | + 'LSUB': ('AUTH', 'SELECTED'), | |
63 | + 'NAMESPACE': ('AUTH', 'SELECTED'), | |
64 | + 'NOOP': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), | |
65 | + 'PARTIAL': ('SELECTED',), # NB: obsolete | |
66 | + 'PROXYAUTH': ('AUTH',), | |
67 | + 'RENAME': ('AUTH', 'SELECTED'), | |
68 | + 'SEARCH': ('SELECTED',), | |
69 | + 'SELECT': ('AUTH', 'SELECTED'), | |
70 | + 'SETACL': ('AUTH', 'SELECTED'), | |
71 | + 'SETANNOTATION':('AUTH', 'SELECTED'), | |
72 | + 'SETQUOTA': ('AUTH', 'SELECTED'), | |
73 | + 'SORT': ('SELECTED',), | |
74 | + 'STATUS': ('AUTH', 'SELECTED'), | |
75 | + 'STORE': ('SELECTED',), | |
76 | + 'SUBSCRIBE': ('AUTH', 'SELECTED'), | |
77 | + 'THREAD': ('SELECTED',), | |
78 | + 'UID': ('SELECTED',), | |
79 | + 'UNSUBSCRIBE': ('AUTH', 'SELECTED'), | |
80 | + } | |
81 | + | |
82 | +# Patterns to match server responses | |
83 | + | |
84 | +Continuation = re.compile(r'\+( (?P<data>.*))?') | |
85 | +Flags = re.compile(r'.*FLAGS \((?P<flags>[^\)]*)\)') | |
86 | +InternalDate = re.compile(r'.*INTERNALDATE "' | |
87 | + r'(?P<day>[ 0123][0-9])-(?P<mon>[A-Z][a-z][a-z])-(?P<year>[0-9][0-9][0-9][0-9])' | |
88 | + r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])' | |
89 | + r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])' | |
90 | + r'"') | |
91 | +Literal = re.compile(r'.*{(?P<size>\d+)}$') | |
92 | +MapCRLF = re.compile(r'\r\n|\r|\n') | |
93 | +Response_code = re.compile(r'\[(?P<type>[A-Z-]+)( (?P<data>[^\]]*))?\]') | |
94 | +Untagged_response = re.compile(r'\* (?P<type>[A-Z-]+)( (?P<data>.*))?') | |
95 | +Untagged_status = re.compile(r'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?') | |
96 | + | |
97 | + | |
98 | + | |
99 | +class IMAP4: | |
100 | + | |
101 | + """IMAP4 client class. | |
102 | + | |
103 | + Instantiate with: IMAP4([host[, port]]) | |
104 | + | |
105 | + host - host's name (default: localhost); | |
106 | + port - port number (default: standard IMAP4 port). | |
107 | + | |
108 | + All IMAP4rev1 commands are supported by methods of the same | |
109 | + name (in lower-case). | |
110 | + | |
111 | + All arguments to commands are converted to strings, except for | |
112 | + AUTHENTICATE, and the last argument to APPEND which is passed as | |
113 | + an IMAP4 literal. If necessary (the string contains any | |
114 | + non-printing characters or white-space and isn't enclosed with | |
115 | + either parentheses or double quotes) each string is quoted. | |
116 | + However, the 'password' argument to the LOGIN command is always | |
117 | + quoted. If you want to avoid having an argument string quoted | |
118 | + (eg: the 'flags' argument to STORE) then enclose the string in | |
119 | + parentheses (eg: "(\Deleted)"). | |
120 | + | |
121 | + Each command returns a tuple: (type, [data, ...]) where 'type' | |
122 | + is usually 'OK' or 'NO', and 'data' is either the text from the | |
123 | + tagged response, or untagged results from command. Each 'data' | |
124 | + is either a string, or a tuple. If a tuple, then the first part | |
125 | + is the header of the response, and the second part contains | |
126 | + the data (ie: 'literal' value). | |
127 | + | |
128 | + Errors raise the exception class <instance>.error("<reason>"). | |
129 | + IMAP4 server errors raise <instance>.abort("<reason>"), | |
130 | + which is a sub-class of 'error'. Mailbox status changes | |
131 | + from READ-WRITE to READ-ONLY raise the exception class | |
132 | + <instance>.readonly("<reason>"), which is a sub-class of 'abort'. | |
133 | + | |
134 | + "error" exceptions imply a program error. | |
135 | + "abort" exceptions imply the connection should be reset, and | |
136 | + the command re-tried. | |
137 | + "readonly" exceptions imply the command should be re-tried. | |
138 | + | |
139 | + Note: to use this module, you must read the RFCs pertaining to the | |
140 | + IMAP4 protocol, as the semantics of the arguments to each IMAP4 | |
141 | + command are left to the invoker, not to mention the results. Also, | |
142 | + most IMAP servers implement a sub-set of the commands available here. | |
143 | + """ | |
144 | + | |
145 | + class error(Exception): pass # Logical errors - debug required | |
146 | + class abort(error): pass # Service errors - close and retry | |
147 | + class readonly(abort): pass # Mailbox status changed to READ-ONLY | |
148 | + | |
149 | + mustquote = re.compile(r"[^\w!#$%&'*+,.:;<=>?^`|~-]") | |
150 | + | |
151 | + def __init__(self, host = '', port = IMAP4_PORT): | |
152 | + self.debug = Debug | |
153 | + self.state = 'LOGOUT' | |
154 | + self.literal = None # A literal argument to a command | |
155 | + self.tagged_commands = {} # Tagged commands awaiting response | |
156 | + self.untagged_responses = {} # {typ: [data, ...], ...} | |
157 | + self.continuation_response = '' # Last continuation response | |
158 | + self.is_readonly = False # READ-ONLY desired state | |
159 | + self.tagnum = 0 | |
160 | + | |
161 | + # Open socket to server. | |
162 | + | |
163 | + self.open(host, port) | |
164 | + | |
165 | + # Create unique tag for this session, | |
166 | + # and compile tagged response matcher. | |
167 | + | |
168 | + self.tagpre = Int2AP(random.randint(4096, 65535)) | |
169 | + self.tagre = re.compile(r'(?P<tag>' | |
170 | + + self.tagpre | |
171 | + + r'\d+) (?P<type>[A-Z]+) (?P<data>.*)') | |
172 | + | |
173 | + # Get server welcome message, | |
174 | + # request and store CAPABILITY response. | |
175 | + | |
176 | + if __debug__: | |
177 | + self._cmd_log_len = 10 | |
178 | + self._cmd_log_idx = 0 | |
179 | + self._cmd_log = {} # Last `_cmd_log_len' interactions | |
180 | + if self.debug >= 1: | |
181 | + self._mesg('imaplib version %s' % __version__) | |
182 | + self._mesg('new IMAP4 connection, tag=%s' % self.tagpre) | |
183 | + | |
184 | + self.welcome = self._get_response() | |
185 | + if 'PREAUTH' in self.untagged_responses: | |
186 | + self.state = 'AUTH' | |
187 | + elif 'OK' in self.untagged_responses: | |
188 | + self.state = 'NONAUTH' | |
189 | + else: | |
190 | + raise self.error(self.welcome) | |
191 | + | |
192 | + typ, dat = self.capability() | |
193 | + if dat == [None]: | |
194 | + raise self.error('no CAPABILITY response from server') | |
195 | + self.capabilities = tuple(dat[-1].upper().split()) | |
196 | + | |
197 | + if __debug__: | |
198 | + if self.debug >= 3: | |
199 | + self._mesg('CAPABILITIES: %r' % (self.capabilities,)) | |
200 | + | |
201 | + for version in AllowedVersions: | |
202 | + if not version in self.capabilities: | |
203 | + continue | |
204 | + self.PROTOCOL_VERSION = version | |
205 | + return | |
206 | + | |
207 | + raise self.error('server not IMAP4 compliant') | |
208 | + | |
209 | + | |
210 | + def __getattr__(self, attr): | |
211 | + # Allow UPPERCASE variants of IMAP4 command methods. | |
212 | + if attr in Commands: | |
213 | + return getattr(self, attr.lower()) | |
214 | + raise AttributeError("Unknown IMAP4 command: '%s'" % attr) | |
215 | + | |
216 | + | |
217 | + | |
218 | + # Overridable methods | |
219 | + | |
220 | + | |
221 | + def open(self, host = '', port = IMAP4_PORT): | |
222 | + """Setup connection to remote server on "host:port" | |
223 | + (default: localhost:standard IMAP4 port). | |
224 | + This connection will be used by the routines: | |
225 | + read, readline, send, shutdown. | |
226 | + """ | |
227 | + self.host = host | |
228 | + self.port = port | |
229 | + self.sock = socket.create_connection((host, port)) | |
230 | + self.file = self.sock.makefile('rb') | |
231 | + | |
232 | + | |
233 | + def read(self, size): | |
234 | + """Read 'size' bytes from remote.""" | |
235 | + return self.file.read(size) | |
236 | + | |
237 | + | |
238 | + def readline(self): | |
239 | + """Read line from remote.""" | |
240 | + return self.file.readline() | |
241 | + | |
242 | + | |
243 | + def send(self, data): | |
244 | + """Send data to remote.""" | |
245 | + self.sock.sendall(data) | |
246 | + | |
247 | + | |
248 | + def shutdown(self): | |
249 | + """Close I/O established in "open".""" | |
250 | + self.file.close() | |
251 | + self.sock.close() | |
252 | + | |
253 | + | |
254 | + def socket(self): | |
255 | + """Return socket instance used to connect to IMAP4 server. | |
256 | + | |
257 | + socket = <instance>.socket() | |
258 | + """ | |
259 | + return self.sock | |
260 | + | |
261 | + | |
262 | + | |
263 | + # Utility methods | |
264 | + | |
265 | + | |
266 | + def recent(self): | |
267 | + """Return most recent 'RECENT' responses if any exist, | |
268 | + else prompt server for an update using the 'NOOP' command. | |
269 | + | |
270 | + (typ, [data]) = <instance>.recent() | |
271 | + | |
272 | + 'data' is None if no new messages, | |
273 | + else list of RECENT responses, most recent last. | |
274 | + """ | |
275 | + name = 'RECENT' | |
276 | + typ, dat = self._untagged_response('OK', [None], name) | |
277 | + if dat[-1]: | |
278 | + return typ, dat | |
279 | + typ, dat = self.noop() # Prod server for response | |
280 | + return self._untagged_response(typ, dat, name) | |
281 | + | |
282 | + | |
283 | + def response(self, code): | |
284 | + """Return data for response 'code' if received, or None. | |
285 | + | |
286 | + Old value for response 'code' is cleared. | |
287 | + | |
288 | + (code, [data]) = <instance>.response(code) | |
289 | + """ | |
290 | + return self._untagged_response(code, [None], code.upper()) | |
291 | + | |
292 | + | |
293 | + | |
294 | + # IMAP4 commands | |
295 | + | |
296 | + | |
297 | + def append(self, mailbox, flags, date_time, message): | |
298 | + """Append message to named mailbox. | |
299 | + | |
300 | + (typ, [data]) = <instance>.append(mailbox, flags, date_time, message) | |
301 | + | |
302 | + All args except `message' can be None. | |
303 | + """ | |
304 | + name = 'APPEND' | |
305 | + if not mailbox: | |
306 | + mailbox = 'INBOX' | |
307 | + if flags: | |
308 | + if (flags[0],flags[-1]) != ('(',')'): | |
309 | + flags = '(%s)' % flags | |
310 | + else: | |
311 | + flags = None | |
312 | + if date_time: | |
313 | + date_time = Time2Internaldate(date_time) | |
314 | + else: | |
315 | + date_time = None | |
316 | + self.literal = MapCRLF.sub(CRLF, message) | |
317 | + return self._simple_command(name, mailbox, flags, date_time) | |
318 | + | |
319 | + | |
320 | + def authenticate(self, mechanism, authobject): | |
321 | + """Authenticate command - requires response processing. | |
322 | + | |
323 | + 'mechanism' specifies which authentication mechanism is to | |
324 | + be used - it must appear in <instance>.capabilities in the | |
325 | + form AUTH=<mechanism>. | |
326 | + | |
327 | + 'authobject' must be a callable object: | |
328 | + | |
329 | + data = authobject(response) | |
330 | + | |
331 | + It will be called to process server continuation responses. | |
332 | + It should return data that will be encoded and sent to server. | |
333 | + It should return None if the client abort response '*' should | |
334 | + be sent instead. | |
335 | + """ | |
336 | + mech = mechanism.upper() | |
337 | + # XXX: shouldn't this code be removed, not commented out? | |
338 | + #cap = 'AUTH=%s' % mech | |
339 | + #if not cap in self.capabilities: # Let the server decide! | |
340 | + # raise self.error("Server doesn't allow %s authentication." % mech) | |
341 | + self.literal = _Authenticator(authobject).process | |
342 | + typ, dat = self._simple_command('AUTHENTICATE', mech) | |
343 | + if typ != 'OK': | |
344 | + raise self.error(dat[-1]) | |
345 | + self.state = 'AUTH' | |
346 | + return typ, dat | |
347 | + | |
348 | + | |
349 | + def capability(self): | |
350 | + """(typ, [data]) = <instance>.capability() | |
351 | + Fetch capabilities list from server.""" | |
352 | + | |
353 | + name = 'CAPABILITY' | |
354 | + typ, dat = self._simple_command(name) | |
355 | + return self._untagged_response(typ, dat, name) | |
356 | + | |
357 | + | |
358 | + def check(self): | |
359 | + """Checkpoint mailbox on server. | |
360 | + | |
361 | + (typ, [data]) = <instance>.check() | |
362 | + """ | |
363 | + return self._simple_command('CHECK') | |
364 | + | |
365 | + | |
366 | + def close(self): | |
367 | + """Close currently selected mailbox. | |
368 | + | |
369 | + Deleted messages are removed from writable mailbox. | |
370 | + This is the recommended command before 'LOGOUT'. | |
371 | + | |
372 | + (typ, [data]) = <instance>.close() | |
373 | + """ | |
374 | + try: | |
375 | + typ, dat = self._simple_command('CLOSE') | |
376 | + finally: | |
377 | + self.state = 'AUTH' | |
378 | + return typ, dat | |
379 | + | |
380 | + | |
381 | + def copy(self, message_set, new_mailbox): | |
382 | + """Copy 'message_set' messages onto end of 'new_mailbox'. | |
383 | + | |
384 | + (typ, [data]) = <instance>.copy(message_set, new_mailbox) | |
385 | + """ | |
386 | + return self._simple_command('COPY', message_set, new_mailbox) | |
387 | + | |
388 | + | |
389 | + def create(self, mailbox): | |
390 | + """Create new mailbox. | |
391 | + | |
392 | + (typ, [data]) = <instance>.create(mailbox) | |
393 | + """ | |
394 | + return self._simple_command('CREATE', mailbox) | |
395 | + | |
396 | + | |
397 | + def delete(self, mailbox): | |
398 | + """Delete old mailbox. | |
399 | + | |
400 | + (typ, [data]) = <instance>.delete(mailbox) | |
401 | + """ | |
402 | + return self._simple_command('DELETE', mailbox) | |
403 | + | |
404 | + def deleteacl(self, mailbox, who): | |
405 | + """Delete the ACLs (remove any rights) set for who on mailbox. | |
406 | + | |
407 | + (typ, [data]) = <instance>.deleteacl(mailbox, who) | |
408 | + """ | |
409 | + return self._simple_command('DELETEACL', mailbox, who) | |
410 | + | |
411 | + def expunge(self): | |
412 | + """Permanently remove deleted items from selected mailbox. | |
413 | + | |
414 | + Generates 'EXPUNGE' response for each deleted message. | |
415 | + | |
416 | + (typ, [data]) = <instance>.expunge() | |
417 | + | |
418 | + 'data' is list of 'EXPUNGE'd message numbers in order received. | |
419 | + """ | |
420 | + name = 'EXPUNGE' | |
421 | + typ, dat = self._simple_command(name) | |
422 | + return self._untagged_response(typ, dat, name) | |
423 | + | |
424 | + | |
425 | + def fetch(self, message_set, message_parts): | |
426 | + """Fetch (parts of) messages. | |
427 | + | |
428 | + (typ, [data, ...]) = <instance>.fetch(message_set, message_parts) | |
429 | + | |
430 | + 'message_parts' should be a string of selected parts | |
431 | + enclosed in parentheses, eg: "(UID BODY[TEXT])". | |
432 | + | |
433 | + 'data' are tuples of message part envelope and data. | |
434 | + """ | |
435 | + name = 'FETCH' | |
436 | + typ, dat = self._simple_command(name, message_set, message_parts) | |
437 | + return self._untagged_response(typ, dat, name) | |
438 | + | |
439 | + | |
440 | + def getacl(self, mailbox): | |
441 | + """Get the ACLs for a mailbox. | |
442 | + | |
443 | + (typ, [data]) = <instance>.getacl(mailbox) | |
444 | + """ | |
445 | + typ, dat = self._simple_command('GETACL', mailbox) | |
446 | + return self._untagged_response(typ, dat, 'ACL') | |
447 | + | |
448 | + | |
449 | + def getannotation(self, mailbox, entry, attribute): | |
450 | + """(typ, [data]) = <instance>.getannotation(mailbox, entry, attribute) | |
451 | + Retrieve ANNOTATIONs.""" | |
452 | + | |
453 | + typ, dat = self._simple_command('GETANNOTATION', mailbox, entry, attribute) | |
454 | + return self._untagged_response(typ, dat, 'ANNOTATION') | |
455 | + | |
456 | + | |
457 | + def getquota(self, root): | |
458 | + """Get the quota root's resource usage and limits. | |
459 | + | |
460 | + Part of the IMAP4 QUOTA extension defined in rfc2087. | |
461 | + | |
462 | + (typ, [data]) = <instance>.getquota(root) | |
463 | + """ | |
464 | + typ, dat = self._simple_command('GETQUOTA', root) | |
465 | + return self._untagged_response(typ, dat, 'QUOTA') | |
466 | + | |
467 | + | |
468 | + def getquotaroot(self, mailbox): | |
469 | + """Get the list of quota roots for the named mailbox. | |
470 | + | |
471 | + (typ, [[QUOTAROOT responses...], [QUOTA responses]]) = <instance>.getquotaroot(mailbox) | |
472 | + """ | |
473 | + typ, dat = self._simple_command('GETQUOTAROOT', mailbox) | |
474 | + typ, quota = self._untagged_response(typ, dat, 'QUOTA') | |
475 | + typ, quotaroot = self._untagged_response(typ, dat, 'QUOTAROOT') | |
476 | + return typ, [quotaroot, quota] | |
477 | + | |
478 | + | |
479 | + def list(self, directory='""', pattern='*'): | |
480 | + """List mailbox names in directory matching pattern. | |
481 | + | |
482 | + (typ, [data]) = <instance>.list(directory='""', pattern='*') | |
483 | + | |
484 | + 'data' is list of LIST responses. | |
485 | + """ | |
486 | + name = 'LIST' | |
487 | + typ, dat = self._simple_command(name, directory, pattern) | |
488 | + return self._untagged_response(typ, dat, name) | |
489 | + | |
490 | + | |
491 | + def login(self, user, password): | |
492 | + """Identify client using plaintext password. | |
493 | + | |
494 | + (typ, [data]) = <instance>.login(user, password) | |
495 | + | |
496 | + NB: 'password' will be quoted. | |
497 | + """ | |
498 | + typ, dat = self._simple_command('LOGIN', user, self._quote(password)) | |
499 | + if typ != 'OK': | |
500 | + raise self.error(dat[-1]) | |
501 | + self.state = 'AUTH' | |
502 | + return typ, dat | |
503 | + | |
504 | + | |
505 | + def login_cram_md5(self, user, password): | |
506 | + """ Force use of CRAM-MD5 authentication. | |
507 | + | |
508 | + (typ, [data]) = <instance>.login_cram_md5(user, password) | |
509 | + """ | |
510 | + self.user, self.password = user, password | |
511 | + return self.authenticate('CRAM-MD5', self._CRAM_MD5_AUTH) | |
512 | + | |
513 | + | |
514 | + def _CRAM_MD5_AUTH(self, challenge): | |
515 | + """ Authobject to use with CRAM-MD5 authentication. """ | |
516 | + import hmac | |
517 | + return self.user + " " + hmac.HMAC(self.password, challenge).hexdigest() | |
518 | + | |
519 | + | |
520 | + def logout(self): | |
521 | + """Shutdown connection to server. | |
522 | + | |
523 | + (typ, [data]) = <instance>.logout() | |
524 | + | |
525 | + Returns server 'BYE' response. | |
526 | + """ | |
527 | + self.state = 'LOGOUT' | |
528 | + try: typ, dat = self._simple_command('LOGOUT') | |
529 | + except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] | |
530 | + self.shutdown() | |
531 | + if 'BYE' in self.untagged_responses: | |
532 | + return 'BYE', self.untagged_responses['BYE'] | |
533 | + return typ, dat | |
534 | + | |
535 | + | |
536 | + def lsub(self, directory='""', pattern='*'): | |
537 | + """List 'subscribed' mailbox names in directory matching pattern. | |
538 | + | |
539 | + (typ, [data, ...]) = <instance>.lsub(directory='""', pattern='*') | |
540 | + | |
541 | + 'data' are tuples of message part envelope and data. | |
542 | + """ | |
543 | + name = 'LSUB' | |
544 | + typ, dat = self._simple_command(name, directory, pattern) | |
545 | + return self._untagged_response(typ, dat, name) | |
546 | + | |
547 | + def myrights(self, mailbox): | |
548 | + """Show my ACLs for a mailbox (i.e. the rights that I have on mailbox). | |
549 | + | |
550 | + (typ, [data]) = <instance>.myrights(mailbox) | |
551 | + """ | |
552 | + typ,dat = self._simple_command('MYRIGHTS', mailbox) | |
553 | + return self._untagged_response(typ, dat, 'MYRIGHTS') | |
554 | + | |
555 | + def namespace(self): | |
556 | + """ Returns IMAP namespaces ala rfc2342 | |
557 | + | |
558 | + (typ, [data, ...]) = <instance>.namespace() | |
559 | + """ | |
560 | + name = 'NAMESPACE' | |
561 | + typ, dat = self._simple_command(name) | |
562 | + return self._untagged_response(typ, dat, name) | |
563 | + | |
564 | + | |
565 | + def noop(self): | |
566 | + """Send NOOP command. | |
567 | + | |
568 | + (typ, [data]) = <instance>.noop() | |
569 | + """ | |
570 | + if __debug__: | |
571 | + if self.debug >= 3: | |
572 | + self._dump_ur(self.untagged_responses) | |
573 | + return self._simple_command('NOOP') | |
574 | + | |
575 | + | |
576 | + def partial(self, message_num, message_part, start, length): | |
577 | + """Fetch truncated part of a message. | |
578 | + | |
579 | + (typ, [data, ...]) = <instance>.partial(message_num, message_part, start, length) | |
580 | + | |
581 | + 'data' is tuple of message part envelope and data. | |
582 | + """ | |
583 | + name = 'PARTIAL' | |
584 | + typ, dat = self._simple_command(name, message_num, message_part, start, length) | |
585 | + return self._untagged_response(typ, dat, 'FETCH') | |
586 | + | |
587 | + | |
588 | + def proxyauth(self, user): | |
589 | + """Assume authentication as "user". | |
590 | + | |
591 | + Allows an authorised administrator to proxy into any user's | |
592 | + mailbox. | |
593 | + | |
594 | + (typ, [data]) = <instance>.proxyauth(user) | |
595 | + """ | |
596 | + | |
597 | + name = 'PROXYAUTH' | |
598 | + return self._simple_command('PROXYAUTH', user) | |
599 | + | |
600 | + | |
601 | + def rename(self, oldmailbox, newmailbox): | |
602 | + """Rename old mailbox name to new. | |
603 | + | |
604 | + (typ, [data]) = <instance>.rename(oldmailbox, newmailbox) | |
605 | + """ | |
606 | + return self._simple_command('RENAME', oldmailbox, newmailbox) | |
607 | + | |
608 | + | |
609 | + def search(self, charset, *criteria): | |
610 | + """Search mailbox for matching messages. | |
611 | + | |
612 | + (typ, [data]) = <instance>.search(charset, criterion, ...) | |
613 | + | |
614 | + 'data' is space separated list of matching message numbers. | |
615 | + """ | |
616 | + name = 'SEARCH' | |
617 | + if charset: | |
618 | + typ, dat = self._simple_command(name, 'CHARSET', charset, *criteria) | |
619 | + else: | |
620 | + typ, dat = self._simple_command(name, *criteria) | |
621 | + return self._untagged_response(typ, dat, name) | |
622 | + | |
623 | + | |
624 | + def select(self, mailbox='INBOX', readonly=False): | |
625 | + """Select a mailbox. | |
626 | + | |
627 | + Flush all untagged responses. | |
628 | + | |
629 | + (typ, [data]) = <instance>.select(mailbox='INBOX', readonly=False) | |
630 | + | |
631 | + 'data' is count of messages in mailbox ('EXISTS' response). | |
632 | + | |
633 | + Mandated responses are ('FLAGS', 'EXISTS', 'RECENT', 'UIDVALIDITY'), so | |
634 | + other responses should be obtained via <instance>.response('FLAGS') etc. | |
635 | + """ | |
636 | + self.untagged_responses = {} # Flush old responses. | |
637 | + self.is_readonly = readonly | |
638 | + if readonly: | |
639 | + name = 'EXAMINE' | |
640 | + else: | |
641 | + name = 'SELECT' | |
642 | + typ, dat = self._simple_command(name, mailbox) | |
643 | + if typ != 'OK': | |
644 | + self.state = 'AUTH' # Might have been 'SELECTED' | |
645 | + return typ, dat | |
646 | + self.state = 'SELECTED' | |
647 | + if 'READ-ONLY' in self.untagged_responses \ | |
648 | + and not readonly: | |
649 | + if __debug__: | |
650 | + if self.debug >= 1: | |
651 | + self._dump_ur(self.untagged_responses) | |
652 | + raise self.readonly('%s is not writable' % mailbox) | |
653 | + return typ, self.untagged_responses.get('EXISTS', [None]) | |
654 | + | |
655 | + | |
656 | + def setacl(self, mailbox, who, what): | |
657 | + """Set a mailbox acl. | |
658 | + | |
659 | + (typ, [data]) = <instance>.setacl(mailbox, who, what) | |
660 | + """ | |
661 | + return self._simple_command('SETACL', mailbox, who, what) | |
662 | + | |
663 | + | |
664 | + def setannotation(self, *args): | |
665 | + """(typ, [data]) = <instance>.setannotation(mailbox[, entry, attribute]+) | |
666 | + Set ANNOTATIONs.""" | |
667 | + | |
668 | + typ, dat = self._simple_command('SETANNOTATION', *args) | |
669 | + return self._untagged_response(typ, dat, 'ANNOTATION') | |
670 | + | |
671 | + | |
672 | + def setquota(self, root, limits): | |
673 | + """Set the quota root's resource limits. | |
674 | + | |
675 | + (typ, [data]) = <instance>.setquota(root, limits) | |
676 | + """ | |
677 | + typ, dat = self._simple_command('SETQUOTA', root, limits) | |
678 | + return self._untagged_response(typ, dat, 'QUOTA') | |
679 | + | |
680 | + | |
681 | + def sort(self, sort_criteria, charset, *search_criteria): | |
682 | + """IMAP4rev1 extension SORT command. | |
683 | + | |
684 | + (typ, [data]) = <instance>.sort(sort_criteria, charset, search_criteria, ...) | |
685 | + """ | |
686 | + name = 'SORT' | |
687 | + #if not name in self.capabilities: # Let the server decide! | |
688 | + # raise self.error('unimplemented extension command: %s' % name) | |
689 | + if (sort_criteria[0],sort_criteria[-1]) != ('(',')'): | |
690 | + sort_criteria = '(%s)' % sort_criteria | |
691 | + typ, dat = self._simple_command(name, sort_criteria, charset, *search_criteria) | |
692 | + return self._untagged_response(typ, dat, name) | |
693 | + | |
694 | + | |
695 | + def status(self, mailbox, names): | |
696 | + """Request named status conditions for mailbox. | |
697 | + | |
698 | + (typ, [data]) = <instance>.status(mailbox, names) | |
699 | + """ | |
700 | + name = 'STATUS' | |
701 | + #if self.PROTOCOL_VERSION == 'IMAP4': # Let the server decide! | |
702 | + # raise self.error('%s unimplemented in IMAP4 (obtain IMAP4rev1 server, or re-code)' % name) | |
703 | + typ, dat = self._simple_command(name, mailbox, names) | |
704 | + return self._untagged_response(typ, dat, name) | |
705 | + | |
706 | + | |
707 | + def store(self, message_set, command, flags): | |
708 | + """Alters flag dispositions for messages in mailbox. | |
709 | + | |
710 | + (typ, [data]) = <instance>.store(message_set, command, flags) | |
711 | + """ | |
712 | + if (flags[0],flags[-1]) != ('(',')'): | |
713 | + flags = '(%s)' % flags # Avoid quoting the flags | |
714 | + typ, dat = self._simple_command('STORE', message_set, command, flags) | |
715 | + return self._untagged_response(typ, dat, 'FETCH') | |
716 | + | |
717 | + | |
718 | + def subscribe(self, mailbox): | |
719 | + """Subscribe to new mailbox. | |
720 | + | |
721 | + (typ, [data]) = <instance>.subscribe(mailbox) | |
722 | + """ | |
723 | + return self._simple_command('SUBSCRIBE', mailbox) | |
724 | + | |
725 | + | |
726 | + def thread(self, threading_algorithm, charset, *search_criteria): | |
727 | + """IMAPrev1 extension THREAD command. | |
728 | + | |
729 | + (type, [data]) = <instance>.thread(threading_algorithm, charset, search_criteria, ...) | |
730 | + """ | |
731 | + name = 'THREAD' | |
732 | + typ, dat = self._simple_command(name, threading_algorithm, charset, *search_criteria) | |
733 | + return self._untagged_response(typ, dat, name) | |
734 | + | |
735 | + | |
736 | + def uid(self, command, *args): | |
737 | + """Execute "command arg ..." with messages identified by UID, | |
738 | + rather than message number. | |
739 | + | |
740 | + (typ, [data]) = <instance>.uid(command, arg1, arg2, ...) | |
741 | + | |
742 | + Returns response appropriate to 'command'. | |
743 | + """ | |
744 | + command = command.upper() | |
745 | + if not command in Commands: | |
746 | + raise self.error("Unknown IMAP4 UID command: %s" % command) | |
747 | + if self.state not in Commands[command]: | |
748 | + raise self.error("command %s illegal in state %s, " | |
749 | + "only allowed in states %s" % | |
750 | + (command, self.state, | |
751 | + ', '.join(Commands[command]))) | |
752 | + name = 'UID' | |
753 | + typ, dat = self._simple_command(name, command, *args) | |
754 | + if command in ('SEARCH', 'SORT'): | |
755 | + name = command | |
756 | + else: | |
757 | + name = 'FETCH' | |
758 | + return self._untagged_response(typ, dat, name) | |
759 | + | |
760 | + | |
761 | + def unsubscribe(self, mailbox): | |
762 | + """Unsubscribe from old mailbox. | |
763 | + | |
764 | + (typ, [data]) = <instance>.unsubscribe(mailbox) | |
765 | + """ | |
766 | + return self._simple_command('UNSUBSCRIBE', mailbox) | |
767 | + | |
768 | + | |
769 | + def xatom(self, name, *args): | |
770 | + """Allow simple extension commands | |
771 | + notified by server in CAPABILITY response. | |
772 | + | |
773 | + Assumes command is legal in current state. | |
774 | + | |
775 | + (typ, [data]) = <instance>.xatom(name, arg, ...) | |
776 | + | |
777 | + Returns response appropriate to extension command `name'. | |
778 | + """ | |
779 | + name = name.upper() | |
780 | + #if not name in self.capabilities: # Let the server decide! | |
781 | + # raise self.error('unknown extension command: %s' % name) | |
782 | + if not name in Commands: | |
783 | + Commands[name] = (self.state,) | |
784 | + return self._simple_command(name, *args) | |
785 | + | |
786 | + | |
787 | + | |
788 | + # Private methods | |
789 | + | |
790 | + | |
791 | + def _append_untagged(self, typ, dat): | |
792 | + | |
793 | + if dat is None: dat = '' | |
794 | + ur = self.untagged_responses | |
795 | + if __debug__: | |
796 | + if self.debug >= 5: | |
797 | + self._mesg('untagged_responses[%s] %s += ["%s"]' % | |
798 | + (typ, len(ur.get(typ,'')), dat)) | |
799 | + if typ in ur: | |
800 | + ur[typ].append(dat) | |
801 | + else: | |
802 | + ur[typ] = [dat] | |
803 | + | |
804 | + | |
805 | + def _check_bye(self): | |
806 | + bye = self.untagged_responses.get('BYE') | |
807 | + if bye: | |
808 | + raise self.abort(bye[-1]) | |
809 | + | |
810 | + | |
811 | + def _command(self, name, *args): | |
812 | + | |
813 | + if self.state not in Commands[name]: | |
814 | + self.literal = None | |
815 | + raise self.error("command %s illegal in state %s, " | |
816 | + "only allowed in states %s" % | |
817 | + (name, self.state, | |
818 | + ', '.join(Commands[name]))) | |
819 | + | |
820 | + for typ in ('OK', 'NO', 'BAD'): | |
821 | + if typ in self.untagged_responses: | |
822 | + del self.untagged_responses[typ] | |
823 | + | |
824 | + if 'READ-ONLY' in self.untagged_responses \ | |
825 | + and not self.is_readonly: | |
826 | + raise self.readonly('mailbox status changed to READ-ONLY') | |
827 | + | |
828 | + tag = self._new_tag() | |
829 | + data = '%s %s' % (tag, name) | |
830 | + for arg in args: | |
831 | + if arg is None: continue | |
832 | + data = '%s %s' % (data, self._checkquote(arg)) | |
833 | + | |
834 | + literal = self.literal | |
835 | + if literal is not None: | |
836 | + self.literal = None | |
837 | + if type(literal) is type(self._command): | |
838 | + literator = literal | |
839 | + else: | |
840 | + literator = None | |
841 | + data = '%s {%s}' % (data, len(literal)) | |
842 | + | |
843 | + if __debug__: | |
844 | + if self.debug >= 4: | |
845 | + self._mesg('> %s' % data) | |
846 | + else: | |
847 | + self._log('> %s' % data) | |
848 | + | |
849 | + try: | |
850 | + self.send('%s%s' % (data, CRLF)) | |
851 | + except (socket.error, OSError), val: | |
852 | + raise self.abort('socket error: %s' % val) | |
853 | + | |
854 | + if literal is None: | |
855 | + return tag | |
856 | + | |
857 | + while 1: | |
858 | + # Wait for continuation response | |
859 | + | |
860 | + while self._get_response(): | |
861 | + if self.tagged_commands[tag]: # BAD/NO? | |
862 | + return tag | |
863 | + | |
864 | + # Send literal | |
865 | + | |
866 | + if literator: | |
867 | + literal = literator(self.continuation_response) | |
868 | + | |
869 | + if __debug__: | |
870 | + if self.debug >= 4: | |
871 | + self._mesg('write literal size %s' % len(literal)) | |
872 | + | |
873 | + try: | |
874 | + self.send(literal) | |
875 | + self.send(CRLF) | |
876 | + except (socket.error, OSError), val: | |
877 | + raise self.abort('socket error: %s' % val) | |
878 | + | |
879 | + if not literator: | |
880 | + break | |
881 | + | |
882 | + return tag | |
883 | + | |
884 | + | |
885 | + def _command_complete(self, name, tag): | |
886 | + self._check_bye() | |
887 | + try: | |
888 | + typ, data = self._get_tagged_response(tag) | |
889 | + except self.abort, val: | |
890 | + raise self.abort('command: %s => %s' % (name, val)) | |
891 | + except self.error, val: | |
892 | + raise self.error('command: %s => %s' % (name, val)) | |
893 | + self._check_bye() | |
894 | + if typ == 'BAD': | |
895 | + raise self.error('%s command error: %s %s' % (name, typ, data)) | |
896 | + return typ, data | |
897 | + | |
898 | + | |
899 | + def _get_response(self): | |
900 | + | |
901 | + # Read response and store. | |
902 | + # | |
903 | + # Returns None for continuation responses, | |
904 | + # otherwise first response line received. | |
905 | + | |
906 | + resp = self._get_line() | |
907 | + | |
908 | + # Command completion response? | |
909 | + | |
910 | + if self._match(self.tagre, resp): | |
911 | + tag = self.mo.group('tag') | |
912 | + if not tag in self.tagged_commands: | |
913 | + raise self.abort('unexpected tagged response: %s' % resp) | |
914 | + | |
915 | + typ = self.mo.group('type') | |
916 | + dat = self.mo.group('data') | |
917 | + self.tagged_commands[tag] = (typ, [dat]) | |
918 | + else: | |
919 | + dat2 = None | |
920 | + | |
921 | + # '*' (untagged) responses? | |
922 | + | |
923 | + if not self._match(Untagged_response, resp): | |
924 | + if self._match(Untagged_status, resp): | |
925 | + dat2 = self.mo.group('data2') | |
926 | + | |
927 | + if self.mo is None: | |
928 | + # Only other possibility is '+' (continuation) response... | |
929 | + | |
930 | + if self._match(Continuation, resp): | |
931 | + self.continuation_response = self.mo.group('data') | |
932 | + return None # NB: indicates continuation | |
933 | + | |
934 | + raise self.abort("unexpected response: '%s'" % resp) | |
935 | + | |
936 | + typ = self.mo.group('type') | |
937 | + dat = self.mo.group('data') | |
938 | + if dat is None: dat = '' # Null untagged response | |
939 | + if dat2: dat = dat + ' ' + dat2 | |
940 | + | |
941 | + # Is there a literal to come? | |
942 | + | |
943 | + while self._match(Literal, dat): | |
944 | + | |
945 | + # Read literal direct from connection. | |
946 | + | |
947 | + size = int(self.mo.group('size')) | |
948 | + if __debug__: | |
949 | + if self.debug >= 4: | |
950 | + self._mesg('read literal size %s' % size) | |
951 | + data = self.read(size) | |
952 | + | |
953 | + # Store response with literal as tuple | |
954 | + | |
955 | + self._append_untagged(typ, (dat, data)) | |
956 | + | |
957 | + # Read trailer - possibly containing another literal | |
958 | + | |
959 | + dat = self._get_line() | |
960 | + | |
961 | + self._append_untagged(typ, dat) | |
962 | + | |
963 | + # Bracketed response information? | |
964 | + | |
965 | + if typ in ('OK', 'NO', 'BAD') and self._match(Response_code, dat): | |
966 | + self._append_untagged(self.mo.group('type'), self.mo.group('data')) | |
967 | + | |
968 | + if __debug__: | |
969 | + if self.debug >= 1 and typ in ('NO', 'BAD', 'BYE'): | |
970 | + self._mesg('%s response: %s' % (typ, dat)) | |
971 | + | |
972 | + return resp | |
973 | + | |
974 | + | |
975 | + def _get_tagged_response(self, tag): | |
976 | + | |
977 | + while 1: | |
978 | + result = self.tagged_commands[tag] | |
979 | + if result is not None: | |
980 | + del self.tagged_commands[tag] | |
981 | + return result | |
982 | + | |
983 | + # Some have reported "unexpected response" exceptions. | |
984 | + # Note that ignoring them here causes loops. | |
985 | + # Instead, send me details of the unexpected response and | |
986 | + # I'll update the code in `_get_response()'. | |
987 | + | |
988 | + try: | |
989 | + self._get_response() | |
990 | + except self.abort, val: | |
991 | + if __debug__: | |
992 | + if self.debug >= 1: | |
993 | + self.print_log() | |
994 | + raise | |
995 | + | |
996 | + | |
997 | + def _get_line(self): | |
998 | + | |
999 | + line = self.readline() | |
1000 | + if not line: | |
1001 | + raise self.abort('socket error: EOF') | |
1002 | + | |
1003 | + # Protocol mandates all lines terminated by CRLF | |
1004 | + if not line.endswith('\r\n'): | |
1005 | + raise self.abort('socket error: unterminated line') | |
1006 | + | |
1007 | + line = line[:-2] | |
1008 | + if __debug__: | |
1009 | + if self.debug >= 4: | |
1010 | + self._mesg('< %s' % line) | |
1011 | + else: | |
1012 | + self._log('< %s' % line) | |
1013 | + return line | |
1014 | + | |
1015 | + | |
1016 | + def _match(self, cre, s): | |
1017 | + | |
1018 | + # Run compiled regular expression match method on 's'. | |
1019 | + # Save result, return success. | |
1020 | + | |
1021 | + self.mo = cre.match(s) | |
1022 | + if __debug__: | |
1023 | + if self.mo is not None and self.debug >= 5: | |
1024 | + self._mesg("\tmatched r'%s' => %r" % (cre.pattern, self.mo.groups())) | |
1025 | + return self.mo is not None | |
1026 | + | |
1027 | + | |
1028 | + def _new_tag(self): | |
1029 | + | |
1030 | + tag = '%s%s' % (self.tagpre, self.tagnum) | |
1031 | + self.tagnum = self.tagnum + 1 | |
1032 | + self.tagged_commands[tag] = None | |
1033 | + return tag | |
1034 | + | |
1035 | + | |
1036 | + def _checkquote(self, arg): | |
1037 | + | |
1038 | + # Must quote command args if non-alphanumeric chars present, | |
1039 | + # and not already quoted. | |
1040 | + | |
1041 | + if type(arg) is not type(''): | |
1042 | + return arg | |
1043 | + if len(arg) >= 2 and (arg[0],arg[-1]) in (('(',')'),('"','"')): | |
1044 | + return arg | |
1045 | + if arg and self.mustquote.search(arg) is None: | |
1046 | + return arg | |
1047 | + return self._quote(arg) | |
1048 | + | |
1049 | + | |
1050 | + def _quote(self, arg): | |
1051 | + | |
1052 | + arg = arg.replace('\\', '\\\\') | |
1053 | + arg = arg.replace('"', '\\"') | |
1054 | + | |
1055 | + return '"%s"' % arg | |
1056 | + | |
1057 | + | |
1058 | + def _simple_command(self, name, *args): | |
1059 | + | |
1060 | + return self._command_complete(name, self._command(name, *args)) | |
1061 | + | |
1062 | + | |
1063 | + def _untagged_response(self, typ, dat, name): | |
1064 | + | |
1065 | + if typ == 'NO': | |
1066 | + return typ, dat | |
1067 | + if not name in self.untagged_responses: | |
1068 | + return typ, [None] | |
1069 | + data = self.untagged_responses.pop(name) | |
1070 | + if __debug__: | |
1071 | + if self.debug >= 5: | |
1072 | + self._mesg('untagged_responses[%s] => %s' % (name, data)) | |
1073 | + return typ, data | |
1074 | + | |
1075 | + | |
1076 | + if __debug__: | |
1077 | + | |
1078 | + def _mesg(self, s, secs=None): | |
1079 | + if secs is None: | |
1080 | + secs = time.time() | |
1081 | + tm = time.strftime('%M:%S', time.localtime(secs)) | |
1082 | + sys.stderr.write(' %s.%02d %s\n' % (tm, (secs*100)%100, s)) | |
1083 | + sys.stderr.flush() | |
1084 | + | |
1085 | + def _dump_ur(self, dict): | |
1086 | + # Dump untagged responses (in `dict'). | |
1087 | + l = dict.items() | |
1088 | + if not l: return | |
1089 | + t = '\n\t\t' | |
1090 | + l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l) | |
1091 | + self._mesg('untagged responses dump:%s%s' % (t, t.join(l))) | |
1092 | + | |
1093 | + def _log(self, line): | |
1094 | + # Keep log of last `_cmd_log_len' interactions for debugging. | |
1095 | + self._cmd_log[self._cmd_log_idx] = (line, time.time()) | |
1096 | + self._cmd_log_idx += 1 | |
1097 | + if self._cmd_log_idx >= self._cmd_log_len: | |
1098 | + self._cmd_log_idx = 0 | |
1099 | + | |
1100 | + def print_log(self): | |
1101 | + self._mesg('last %d IMAP4 interactions:' % len(self._cmd_log)) | |
1102 | + i, n = self._cmd_log_idx, self._cmd_log_len | |
1103 | + while n: | |
1104 | + try: | |
1105 | + self._mesg(*self._cmd_log[i]) | |
1106 | + except: | |
1107 | + pass | |
1108 | + i += 1 | |
1109 | + if i >= self._cmd_log_len: | |
1110 | + i = 0 | |
1111 | + n -= 1 | |
1112 | + | |
1113 | + | |
1114 | + | |
1115 | +try: | |
1116 | + import ssl | |
1117 | +except ImportError: | |
1118 | + pass | |
1119 | +else: | |
1120 | + class IMAP4_SSL(IMAP4): | |
1121 | + | |
1122 | + """IMAP4 client class over SSL connection | |
1123 | + | |
1124 | + Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) | |
1125 | + | |
1126 | + host - host's name (default: localhost); | |
1127 | + port - port number (default: standard IMAP4 SSL port). | |
1128 | + keyfile - PEM formatted file that contains your private key (default: None); | |
1129 | + certfile - PEM formatted certificate chain file (default: None); | |
1130 | + | |
1131 | + for more documentation see the docstring of the parent class IMAP4. | |
1132 | + """ | |
1133 | + | |
1134 | + | |
1135 | + def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None): | |
1136 | + self.keyfile = keyfile | |
1137 | + self.certfile = certfile | |
1138 | + IMAP4.__init__(self, host, port) | |
1139 | + | |
1140 | + | |
1141 | + def open(self, host = '', port = IMAP4_SSL_PORT): | |
1142 | + """Setup connection to remote server on "host:port". | |
1143 | + (default: localhost:standard IMAP4 SSL port). | |
1144 | + This connection will be used by the routines: | |
1145 | + read, readline, send, shutdown. | |
1146 | + """ | |
1147 | + self.host = host | |
1148 | + self.port = port | |
1149 | + self.sock = socket.create_connection((host, port)) | |
1150 | + self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) | |
1151 | + | |
1152 | + | |
1153 | + def read(self, size): | |
1154 | + """Read 'size' bytes from remote.""" | |
1155 | + # sslobj.read() sometimes returns < size bytes | |
1156 | + chunks = [] | |
1157 | + read = 0 | |
1158 | + while read < size: | |
1159 | + data = self.sslobj.read(min(size-read, 16384)) | |
1160 | + read += len(data) | |
1161 | + chunks.append(data) | |
1162 | + | |
1163 | + return ''.join(chunks) | |
1164 | + | |
1165 | + | |
1166 | + def readline(self): | |
1167 | + """Read line from remote.""" | |
1168 | + line = [] | |
1169 | + while 1: | |
1170 | + char = self.sslobj.read(1) | |
1171 | + line.append(char) | |
1172 | + if char in ("\n", ""): return ''.join(line) | |
1173 | + | |
1174 | + | |
1175 | + def send(self, data): | |
1176 | + """Send data to remote.""" | |
1177 | + bytes = len(data) | |
1178 | + while bytes > 0: | |
1179 | + sent = self.sslobj.write(data) | |
1180 | + if sent == bytes: | |
1181 | + break # avoid copy | |
1182 | + data = data[sent:] | |
1183 | + bytes = bytes - sent | |
1184 | + | |
1185 | + | |
1186 | + def shutdown(self): | |
1187 | + """Close I/O established in "open".""" | |
1188 | + self.sock.close() | |
1189 | + | |
1190 | + | |
1191 | + def socket(self): | |
1192 | + """Return socket instance used to connect to IMAP4 server. | |
1193 | + | |
1194 | + socket = <instance>.socket() | |
1195 | + """ | |
1196 | + return self.sock | |
1197 | + | |
1198 | + | |
1199 | + def ssl(self): | |
1200 | + """Return SSLObject instance used to communicate with the IMAP4 server. | |
1201 | + | |
1202 | + ssl = ssl.wrap_socket(<instance>.socket) | |
1203 | + """ | |
1204 | + return self.sslobj | |
1205 | + | |
1206 | + __all__.append("IMAP4_SSL") | |
1207 | + | |
1208 | + | |
1209 | +class IMAP4_stream(IMAP4): | |
1210 | + | |
1211 | + """IMAP4 client class over a stream | |
1212 | + | |
1213 | + Instantiate with: IMAP4_stream(command) | |
1214 | + | |
1215 | + where "command" is a string that can be passed to subprocess.Popen() | |
1216 | + | |
1217 | + for more documentation see the docstring of the parent class IMAP4. | |
1218 | + """ | |
1219 | + | |
1220 | + | |
1221 | + def __init__(self, command): | |
1222 | + self.command = command | |
1223 | + IMAP4.__init__(self) | |
1224 | + | |
1225 | + | |
1226 | + def open(self, host = None, port = None): | |
1227 | + """Setup a stream connection. | |
1228 | + This connection will be used by the routines: | |
1229 | + read, readline, send, shutdown. | |
1230 | + """ | |
1231 | + self.host = None # For compatibility with parent class | |
1232 | + self.port = None | |
1233 | + self.sock = None | |
1234 | + self.file = None | |
1235 | + self.process = subprocess.Popen(self.command, | |
1236 | + stdin=subprocess.PIPE, stdout=subprocess.PIPE, | |
1237 | + shell=True, close_fds=True) | |
1238 | + self.writefile = self.process.stdin | |
1239 | + self.readfile = self.process.stdout | |
1240 | + | |
1241 | + | |
1242 | + def read(self, size): | |
1243 | + """Read 'size' bytes from remote.""" | |
1244 | + return self.readfile.read(size) | |
1245 | + | |
1246 | + | |
1247 | + def readline(self): | |
1248 | + """Read line from remote.""" | |
1249 | + return self.readfile.readline() | |
1250 | + | |
1251 | + | |
1252 | + def send(self, data): | |
1253 | + """Send data to remote.""" | |
1254 | + self.writefile.write(data) | |
1255 | + self.writefile.flush() | |
1256 | + | |
1257 | + | |
1258 | + def shutdown(self): | |
1259 | + """Close I/O established in "open".""" | |
1260 | + self.readfile.close() | |
1261 | + self.writefile.close() | |
1262 | + self.process.wait() | |
1263 | + | |
1264 | + | |
1265 | + | |
1266 | +class _Authenticator: | |
1267 | + | |
1268 | + """Private class to provide en/decoding | |
1269 | + for base64-based authentication conversation. | |
1270 | + """ | |
1271 | + | |
1272 | + def __init__(self, mechinst): | |
1273 | + self.mech = mechinst # Callable object to provide/process data | |
1274 | + | |
1275 | + def process(self, data): | |
1276 | + ret = self.mech(self.decode(data)) | |
1277 | + if ret is None: | |
1278 | + return '*' # Abort conversation | |
1279 | + return self.encode(ret) | |
1280 | + | |
1281 | + def encode(self, inp): | |
1282 | + # | |
1283 | + # Invoke binascii.b2a_base64 iteratively with | |
1284 | + # short even length buffers, strip the trailing | |
1285 | + # line feed from the result and append. "Even" | |
1286 | + # means a number that factors to both 6 and 8, | |
1287 | + # so when it gets to the end of the 8-bit input | |
1288 | + # there's no partial 6-bit output. | |
1289 | + # | |
1290 | + oup = '' | |
1291 | + while inp: | |
1292 | + if len(inp) > 48: | |
1293 | + t = inp[:48] | |
1294 | + inp = inp[48:] | |
1295 | + else: | |
1296 | + t = inp | |
1297 | + inp = '' | |
1298 | + e = binascii.b2a_base64(t) | |
1299 | + if e: | |
1300 | + oup = oup + e[:-1] | |
1301 | + return oup | |
1302 | + | |
1303 | + def decode(self, inp): | |
1304 | + if not inp: | |
1305 | + return '' | |
1306 | + return binascii.a2b_base64(inp) | |
1307 | + | |
1308 | + | |
1309 | + | |
1310 | +Mon2num = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, | |
1311 | + 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12} | |
1312 | + | |
1313 | +def Internaldate2tuple(resp): | |
1314 | + """Convert IMAP4 INTERNALDATE to UT. | |
1315 | + | |
1316 | + Returns Python time module tuple. | |
1317 | + """ | |
1318 | + | |
1319 | + mo = InternalDate.match(resp) | |
1320 | + if not mo: | |
1321 | + return None | |
1322 | + | |
1323 | + mon = Mon2num[mo.group('mon')] | |
1324 | + zonen = mo.group('zonen') | |
1325 | + | |
1326 | + day = int(mo.group('day')) | |
1327 | + year = int(mo.group('year')) | |
1328 | + hour = int(mo.group('hour')) | |
1329 | + min = int(mo.group('min')) | |
1330 | + sec = int(mo.group('sec')) | |
1331 | + zoneh = int(mo.group('zoneh')) | |
1332 | + zonem = int(mo.group('zonem')) | |
1333 | + | |
1334 | + # INTERNALDATE timezone must be subtracted to get UT | |
1335 | + | |
1336 | + zone = (zoneh*60 + zonem)*60 | |
1337 | + if zonen == '-': | |
1338 | + zone = -zone | |
1339 | + | |
1340 | + tt = (year, mon, day, hour, min, sec, -1, -1, -1) | |
1341 | + | |
1342 | + utc = time.mktime(tt) | |
1343 | + | |
1344 | + # Following is necessary because the time module has no 'mkgmtime'. | |
1345 | + # 'mktime' assumes arg in local timezone, so adds timezone/altzone. | |
1346 | + | |
1347 | + lt = time.localtime(utc) | |
1348 | + if time.daylight and lt[-1]: | |
1349 | + zone = zone + time.altzone | |
1350 | + else: | |
1351 | + zone = zone + time.timezone | |
1352 | + | |
1353 | + return time.localtime(utc - zone) | |
1354 | + | |
1355 | + | |
1356 | + | |
1357 | +def Int2AP(num): | |
1358 | + | |
1359 | + """Convert integer to A-P string representation.""" | |
1360 | + | |
1361 | + val = ''; AP = 'ABCDEFGHIJKLMNOP' | |
1362 | + num = int(abs(num)) | |
1363 | + while num: | |
1364 | + num, mod = divmod(num, 16) | |
1365 | + val = AP[mod] + val | |
1366 | + return val | |
1367 | + | |
1368 | + | |
1369 | + | |
1370 | +def ParseFlags(resp): | |
1371 | + | |
1372 | + """Convert IMAP4 flags response to python tuple.""" | |
1373 | + | |
1374 | + mo = Flags.match(resp) | |
1375 | + if not mo: | |
1376 | + return () | |
1377 | + | |
1378 | + return tuple(mo.group('flags').split()) | |
1379 | + | |
1380 | + | |
1381 | +def Time2Internaldate(date_time): | |
1382 | + | |
1383 | + """Convert 'date_time' to IMAP4 INTERNALDATE representation. | |
1384 | + | |
1385 | + Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"' | |
1386 | + """ | |
1387 | + | |
1388 | + if isinstance(date_time, (int, float)): | |
1389 | + tt = time.localtime(date_time) | |
1390 | + elif isinstance(date_time, (tuple, time.struct_time)): | |
1391 | + tt = date_time | |
1392 | + elif isinstance(date_time, str) and (date_time[0],date_time[-1]) == ('"','"'): | |
1393 | + return date_time # Assume in correct format | |
1394 | + else: | |
1395 | + raise ValueError("date_time not of a known type") | |
1396 | + | |
1397 | + dt = time.strftime("%d-%b-%Y %H:%M:%S", tt) | |
1398 | + if dt[0] == '0': | |
1399 | + dt = ' ' + dt[1:] | |
1400 | + if time.daylight and tt[-1]: | |
1401 | + zone = -time.altzone | |
1402 | + else: | |
1403 | + zone = -time.timezone | |
1404 | + return '"' + dt + " %+03d%02d" % divmod(zone//60, 60) + '"' | |
1405 | + | |
1406 | + | |
1407 | + | |
1408 | +if __name__ == '__main__': | |
1409 | + | |
1410 | + # To test: invoke either as 'python imaplib.py [IMAP4_server_hostname]' | |
1411 | + # or 'python imaplib.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"' | |
1412 | + # to test the IMAP4_stream class | |
1413 | + | |
1414 | + import getopt, getpass | |
1415 | + | |
1416 | + try: | |
1417 | + optlist, args = getopt.getopt(sys.argv[1:], 'd:s:') | |
1418 | + except getopt.error, val: | |
1419 | + optlist, args = (), () | |
1420 | + | |
1421 | + stream_command = None | |
1422 | + for opt,val in optlist: | |
1423 | + if opt == '-d': | |
1424 | + Debug = int(val) | |
1425 | + elif opt == '-s': | |
1426 | + stream_command = val | |
1427 | + if not args: args = (stream_command,) | |
1428 | + | |
1429 | + if not args: args = ('',) | |
1430 | + | |
1431 | + host = args[0] | |
1432 | + | |
1433 | + USER = getpass.getuser() | |
1434 | + PASSWD = getpass.getpass("IMAP password for %s on %s: " % (USER, host or "localhost")) | |
1435 | + | |
1436 | + test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)sdata...%(lf)s' % {'user':USER, 'lf':'\n'} | |
1437 | + test_seq1 = ( | |
1438 | + ('login', (USER, PASSWD)), | |
1439 | + ('create', ('/tmp/xxx 1',)), | |
1440 | + ('rename', ('/tmp/xxx 1', '/tmp/yyy')), | |
1441 | + ('CREATE', ('/tmp/yyz 2',)), | |
1442 | + ('append', ('/tmp/yyz 2', None, None, test_mesg)), | |
1443 | + ('list', ('/tmp', 'yy*')), | |
1444 | + ('select', ('/tmp/yyz 2',)), | |
1445 | + ('search', (None, 'SUBJECT', 'test')), | |
1446 | + ('fetch', ('1', '(FLAGS INTERNALDATE RFC822)')), | |
1447 | + ('store', ('1', 'FLAGS', '(\Deleted)')), | |
1448 | + ('namespace', ()), | |
1449 | + ('expunge', ()), | |
1450 | + ('recent', ()), | |
1451 | + ('close', ()), | |
1452 | + ) | |
1453 | + | |
1454 | + test_seq2 = ( | |
1455 | + ('select', ()), | |
1456 | + ('response',('UIDVALIDITY',)), | |
1457 | + ('uid', ('SEARCH', 'ALL')), | |
1458 | + ('response', ('EXISTS',)), | |
1459 | + ('append', (None, None, None, test_mesg)), | |
1460 | + ('recent', ()), | |
1461 | + ('logout', ()), | |
1462 | + ) | |
1463 | + | |
1464 | + def run(cmd, args): | |
1465 | + M._mesg('%s %s' % (cmd, args)) | |
1466 | + typ, dat = getattr(M, cmd)(*args) | |
1467 | + M._mesg('%s => %s %s' % (cmd, typ, dat)) | |
1468 | + if typ == 'NO': raise dat[0] | |
1469 | + return dat | |
1470 | + | |
1471 | + try: | |
1472 | + if stream_command: | |
1473 | + M = IMAP4_stream(stream_command) | |
1474 | + else: | |
1475 | + M = IMAP4(host) | |
1476 | + if M.state == 'AUTH': | |
1477 | + test_seq1 = test_seq1[1:] # Login not needed | |
1478 | + M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION) | |
1479 | + M._mesg('CAPABILITIES = %r' % (M.capabilities,)) | |
1480 | + | |
1481 | + for cmd,args in test_seq1: | |
1482 | + run(cmd, args) | |
1483 | + | |
1484 | + for ml in run('list', ('/tmp/', 'yy%')): | |
1485 | + mo = re.match(r'.*"([^"]+)"$', ml) | |
1486 | + if mo: path = mo.group(1) | |
1487 | + else: path = ml.split()[-1] | |
1488 | + run('delete', (path,)) | |
1489 | + | |
1490 | + for cmd,args in test_seq2: | |
1491 | + dat = run(cmd, args) | |
1492 | + | |
1493 | + if (cmd,args) != ('uid', ('SEARCH', 'ALL')): | |
1494 | + continue | |
1495 | + | |
1496 | + uid = dat[-1].split() | |
1497 | + if not uid: continue | |
1498 | + run('uid', ('FETCH', '%s' % uid[-1], | |
1499 | + '(FLAGS INTERNALDATE RFC822.SIZE RFC822.HEADER RFC822.TEXT)')) | |
1500 | + | |
1501 | + print '\nAll tests OK.' | |
1502 | + | |
1503 | + except: | |
1504 | + print '\nTests failed.' | |
1505 | + | |
1506 | + if not Debug: | |
1507 | + print ''' | |
1508 | +If you would like to see debugging output, | |
1509 | +try: %s -d5 | |
1510 | +''' % sys.argv[0] | |
1511 | + | |
1512 | + raise |
@@ -1,3 +1,3 @@ | ||
1 | -# coding: utf-8 | |
1 | +# coding: utf-8 | |
2 | 2 | print "BOM BOOM!" |
3 | 3 |
@@ -38,8 +38,8 @@ class shlex: | ||
38 | 38 | self.wordchars = ('abcdfeghijklmnopqrstuvwxyz' |
39 | 39 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_') |
40 | 40 | if self.posix: |
41 | - self.wordchars += ('鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申' | |
42 | - '鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申鐃緒申') | |
41 | + self.wordchars += ('烙痰邃繙艾蜉謖邇關髓齡?????' | |
42 | + '請唾津毒班碧麺力佰厶壞嶷掣桀毳') | |
43 | 43 | self.whitespace = ' \t\r\n' |
44 | 44 | self.whitespace_split = False |
45 | 45 | self.quotes = '\'"' |
@@ -0,0 +1,2 @@ | ||
1 | +This directory exists so that 3rd party packages can be installed | |
2 | +here. Read the source for site.py for more details. |
@@ -0,0 +1,443 @@ | ||
1 | +# Wrapper module for _ssl, providing some additional facilities | |
2 | +# implemented in Python. Written by Bill Janssen. | |
3 | + | |
4 | +"""\ | |
5 | +This module provides some more Pythonic support for SSL. | |
6 | + | |
7 | +Object types: | |
8 | + | |
9 | + SSLSocket -- subtype of socket.socket which does SSL over the socket | |
10 | + | |
11 | +Exceptions: | |
12 | + | |
13 | + SSLError -- exception raised for I/O errors | |
14 | + | |
15 | +Functions: | |
16 | + | |
17 | + cert_time_to_seconds -- convert time string used for certificate | |
18 | + notBefore and notAfter functions to integer | |
19 | + seconds past the Epoch (the time values | |
20 | + returned from time.time()) | |
21 | + | |
22 | + fetch_server_certificate (HOST, PORT) -- fetch the certificate provided | |
23 | + by the server running on HOST at port PORT. No | |
24 | + validation of the certificate is performed. | |
25 | + | |
26 | +Integer constants: | |
27 | + | |
28 | +SSL_ERROR_ZERO_RETURN | |
29 | +SSL_ERROR_WANT_READ | |
30 | +SSL_ERROR_WANT_WRITE | |
31 | +SSL_ERROR_WANT_X509_LOOKUP | |
32 | +SSL_ERROR_SYSCALL | |
33 | +SSL_ERROR_SSL | |
34 | +SSL_ERROR_WANT_CONNECT | |
35 | + | |
36 | +SSL_ERROR_EOF | |
37 | +SSL_ERROR_INVALID_ERROR_CODE | |
38 | + | |
39 | +The following group define certificate requirements that one side is | |
40 | +allowing/requiring from the other side: | |
41 | + | |
42 | +CERT_NONE - no certificates from the other side are required (or will | |
43 | + be looked at if provided) | |
44 | +CERT_OPTIONAL - certificates are not required, but if provided will be | |
45 | + validated, and if validation fails, the connection will | |
46 | + also fail | |
47 | +CERT_REQUIRED - certificates are required, and will be validated, and | |
48 | + if validation fails, the connection will also fail | |
49 | + | |
50 | +The following constants identify various SSL protocol variants: | |
51 | + | |
52 | +PROTOCOL_SSLv2 | |
53 | +PROTOCOL_SSLv3 | |
54 | +PROTOCOL_SSLv23 | |
55 | +PROTOCOL_TLSv1 | |
56 | +""" | |
57 | + | |
58 | +import textwrap | |
59 | + | |
60 | +import _ssl # if we can't import it, let the error propagate | |
61 | + | |
62 | +from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION | |
63 | +from _ssl import SSLError | |
64 | +from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED | |
65 | +from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 | |
66 | +from _ssl import RAND_status, RAND_egd, RAND_add | |
67 | +from _ssl import \ | |
68 | + SSL_ERROR_ZERO_RETURN, \ | |
69 | + SSL_ERROR_WANT_READ, \ | |
70 | + SSL_ERROR_WANT_WRITE, \ | |
71 | + SSL_ERROR_WANT_X509_LOOKUP, \ | |
72 | + SSL_ERROR_SYSCALL, \ | |
73 | + SSL_ERROR_SSL, \ | |
74 | + SSL_ERROR_WANT_CONNECT, \ | |
75 | + SSL_ERROR_EOF, \ | |
76 | + SSL_ERROR_INVALID_ERROR_CODE | |
77 | + | |
78 | +from socket import socket, _fileobject, _delegate_methods, error as socket_error | |
79 | +from socket import getnameinfo as _getnameinfo | |
80 | +import base64 # for DER-to-PEM translation | |
81 | +import errno | |
82 | + | |
83 | +class SSLSocket(socket): | |
84 | + | |
85 | + """This class implements a subtype of socket.socket that wraps | |
86 | + the underlying OS socket in an SSL context when necessary, and | |
87 | + provides read and write methods over that channel.""" | |
88 | + | |
89 | + def __init__(self, sock, keyfile=None, certfile=None, | |
90 | + server_side=False, cert_reqs=CERT_NONE, | |
91 | + ssl_version=PROTOCOL_SSLv23, ca_certs=None, | |
92 | + do_handshake_on_connect=True, | |
93 | + suppress_ragged_eofs=True, ciphers=None): | |
94 | + socket.__init__(self, _sock=sock._sock) | |
95 | + # The initializer for socket overrides the methods send(), recv(), etc. | |
96 | + # in the instancce, which we don't need -- but we want to provide the | |
97 | + # methods defined in SSLSocket. | |
98 | + for attr in _delegate_methods: | |
99 | + try: | |
100 | + delattr(self, attr) | |
101 | + except AttributeError: | |
102 | + pass | |
103 | + | |
104 | + if certfile and not keyfile: | |
105 | + keyfile = certfile | |
106 | + # see if it's connected | |
107 | + try: | |
108 | + socket.getpeername(self) | |
109 | + except socket_error, e: | |
110 | + if e.errno != errno.ENOTCONN: | |
111 | + raise | |
112 | + # no, no connection yet | |
113 | + self._sslobj = None | |
114 | + else: | |
115 | + # yes, create the SSL object | |
116 | + self._sslobj = _ssl.sslwrap(self._sock, server_side, | |
117 | + keyfile, certfile, | |
118 | + cert_reqs, ssl_version, ca_certs, | |
119 | + ciphers) | |
120 | + if do_handshake_on_connect: | |
121 | + self.do_handshake() | |
122 | + self.keyfile = keyfile | |
123 | + self.certfile = certfile | |
124 | + self.cert_reqs = cert_reqs | |
125 | + self.ssl_version = ssl_version | |
126 | + self.ca_certs = ca_certs | |
127 | + self.ciphers = ciphers | |
128 | + self.do_handshake_on_connect = do_handshake_on_connect | |
129 | + self.suppress_ragged_eofs = suppress_ragged_eofs | |
130 | + self._makefile_refs = 0 | |
131 | + | |
132 | + def read(self, len=1024): | |
133 | + | |
134 | + """Read up to LEN bytes and return them. | |
135 | + Return zero-length string on EOF.""" | |
136 | + | |
137 | + try: | |
138 | + return self._sslobj.read(len) | |
139 | + except SSLError, x: | |
140 | + if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: | |
141 | + return '' | |
142 | + else: | |
143 | + raise | |
144 | + | |
145 | + def write(self, data): | |
146 | + | |
147 | + """Write DATA to the underlying SSL channel. Returns | |
148 | + number of bytes of DATA actually transmitted.""" | |
149 | + | |
150 | + return self._sslobj.write(data) | |
151 | + | |
152 | + def getpeercert(self, binary_form=False): | |
153 | + | |
154 | + """Returns a formatted version of the data in the | |
155 | + certificate provided by the other end of the SSL channel. | |
156 | + Return None if no certificate was provided, {} if a | |
157 | + certificate was provided, but not validated.""" | |
158 | + | |
159 | + return self._sslobj.peer_certificate(binary_form) | |
160 | + | |
161 | + def cipher(self): | |
162 | + | |
163 | + if not self._sslobj: | |
164 | + return None | |
165 | + else: | |
166 | + return self._sslobj.cipher() | |
167 | + | |
168 | + def send(self, data, flags=0): | |
169 | + if self._sslobj: | |
170 | + if flags != 0: | |
171 | + raise ValueError( | |
172 | + "non-zero flags not allowed in calls to send() on %s" % | |
173 | + self.__class__) | |
174 | + while True: | |
175 | + try: | |
176 | + v = self._sslobj.write(data) | |
177 | + except SSLError, x: | |
178 | + if x.args[0] == SSL_ERROR_WANT_READ: | |
179 | + return 0 | |
180 | + elif x.args[0] == SSL_ERROR_WANT_WRITE: | |
181 | + return 0 | |
182 | + else: | |
183 | + raise | |
184 | + else: | |
185 | + return v | |
186 | + else: | |
187 | + return socket.send(self, data, flags) | |
188 | + | |
189 | + def sendto(self, data, addr, flags=0): | |
190 | + if self._sslobj: | |
191 | + raise ValueError("sendto not allowed on instances of %s" % | |
192 | + self.__class__) | |
193 | + else: | |
194 | + return socket.sendto(self, data, addr, flags) | |
195 | + | |
196 | + def sendall(self, data, flags=0): | |
197 | + if self._sslobj: | |
198 | + if flags != 0: | |
199 | + raise ValueError( | |
200 | + "non-zero flags not allowed in calls to sendall() on %s" % | |
201 | + self.__class__) | |
202 | + amount = len(data) | |
203 | + count = 0 | |
204 | + while (count < amount): | |
205 | + v = self.send(data[count:]) | |
206 | + count += v | |
207 | + return amount | |
208 | + else: | |
209 | + return socket.sendall(self, data, flags) | |
210 | + | |
211 | + def recv(self, buflen=1024, flags=0): | |
212 | + if self._sslobj: | |
213 | + if flags != 0: | |
214 | + raise ValueError( | |
215 | + "non-zero flags not allowed in calls to recv() on %s" % | |
216 | + self.__class__) | |
217 | + return self.read(buflen) | |
218 | + else: | |
219 | + return socket.recv(self, buflen, flags) | |
220 | + | |
221 | + def recv_into(self, buffer, nbytes=None, flags=0): | |
222 | + if buffer and (nbytes is None): | |
223 | + nbytes = len(buffer) | |
224 | + elif nbytes is None: | |
225 | + nbytes = 1024 | |
226 | + if self._sslobj: | |
227 | + if flags != 0: | |
228 | + raise ValueError( | |
229 | + "non-zero flags not allowed in calls to recv_into() on %s" % | |
230 | + self.__class__) | |
231 | + tmp_buffer = self.read(nbytes) | |
232 | + v = len(tmp_buffer) | |
233 | + buffer[:v] = tmp_buffer | |
234 | + return v | |
235 | + else: | |
236 | + return socket.recv_into(self, buffer, nbytes, flags) | |
237 | + | |
238 | + def recvfrom(self, addr, buflen=1024, flags=0): | |
239 | + if self._sslobj: | |
240 | + raise ValueError("recvfrom not allowed on instances of %s" % | |
241 | + self.__class__) | |
242 | + else: | |
243 | + return socket.recvfrom(self, addr, buflen, flags) | |
244 | + | |
245 | + def recvfrom_into(self, buffer, nbytes=None, flags=0): | |
246 | + if self._sslobj: | |
247 | + raise ValueError("recvfrom_into not allowed on instances of %s" % | |
248 | + self.__class__) | |
249 | + else: | |
250 | + return socket.recvfrom_into(self, buffer, nbytes, flags) | |
251 | + | |
252 | + def pending(self): | |
253 | + if self._sslobj: | |
254 | + return self._sslobj.pending() | |
255 | + else: | |
256 | + return 0 | |
257 | + | |
258 | + def unwrap(self): | |
259 | + if self._sslobj: | |
260 | + s = self._sslobj.shutdown() | |
261 | + self._sslobj = None | |
262 | + return s | |
263 | + else: | |
264 | + raise ValueError("No SSL wrapper around " + str(self)) | |
265 | + | |
266 | + def shutdown(self, how): | |
267 | + self._sslobj = None | |
268 | + socket.shutdown(self, how) | |
269 | + | |
270 | + def close(self): | |
271 | + if self._makefile_refs < 1: | |
272 | + self._sslobj = None | |
273 | + socket.close(self) | |
274 | + else: | |
275 | + self._makefile_refs -= 1 | |
276 | + | |
277 | + def do_handshake(self): | |
278 | + | |
279 | + """Perform a TLS/SSL handshake.""" | |
280 | + | |
281 | + self._sslobj.do_handshake() | |
282 | + | |
283 | + def connect(self, addr): | |
284 | + | |
285 | + """Connects to remote ADDR, and then wraps the connection in | |
286 | + an SSL channel.""" | |
287 | + | |
288 | + # Here we assume that the socket is client-side, and not | |
289 | + # connected at the time of the call. We connect it, then wrap it. | |
290 | + if self._sslobj: | |
291 | + raise ValueError("attempt to connect already-connected SSLSocket!") | |
292 | + socket.connect(self, addr) | |
293 | + self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, | |
294 | + self.cert_reqs, self.ssl_version, | |
295 | + self.ca_certs, self.ciphers) | |
296 | + if self.do_handshake_on_connect: | |
297 | + self.do_handshake() | |
298 | + | |
299 | + def accept(self): | |
300 | + | |
301 | + """Accepts a new connection from a remote client, and returns | |
302 | + a tuple containing that new connection wrapped with a server-side | |
303 | + SSL channel, and the address of the remote client.""" | |
304 | + | |
305 | + newsock, addr = socket.accept(self) | |
306 | + return (SSLSocket(newsock, | |
307 | + keyfile=self.keyfile, | |
308 | + certfile=self.certfile, | |
309 | + server_side=True, | |
310 | + cert_reqs=self.cert_reqs, | |
311 | + ssl_version=self.ssl_version, | |
312 | + ca_certs=self.ca_certs, | |
313 | + ciphers=self.ciphers, | |
314 | + do_handshake_on_connect=self.do_handshake_on_connect, | |
315 | + suppress_ragged_eofs=self.suppress_ragged_eofs), | |
316 | + addr) | |
317 | + | |
318 | + def makefile(self, mode='r', bufsize=-1): | |
319 | + | |
320 | + """Make and return a file-like object that | |
321 | + works with the SSL connection. Just use the code | |
322 | + from the socket module.""" | |
323 | + | |
324 | + self._makefile_refs += 1 | |
325 | + # close=True so as to decrement the reference count when done with | |
326 | + # the file-like object. | |
327 | + return _fileobject(self, mode, bufsize, close=True) | |
328 | + | |
329 | + | |
330 | + | |
331 | +def wrap_socket(sock, keyfile=None, certfile=None, | |
332 | + server_side=False, cert_reqs=CERT_NONE, | |
333 | + ssl_version=PROTOCOL_SSLv23, ca_certs=None, | |
334 | + do_handshake_on_connect=True, | |
335 | + suppress_ragged_eofs=True, ciphers=None): | |
336 | + | |
337 | + return SSLSocket(sock, keyfile=keyfile, certfile=certfile, | |
338 | + server_side=server_side, cert_reqs=cert_reqs, | |
339 | + ssl_version=ssl_version, ca_certs=ca_certs, | |
340 | + do_handshake_on_connect=do_handshake_on_connect, | |
341 | + suppress_ragged_eofs=suppress_ragged_eofs, | |
342 | + ciphers=ciphers) | |
343 | + | |
344 | + | |
345 | +# some utility functions | |
346 | + | |
347 | +def cert_time_to_seconds(cert_time): | |
348 | + | |
349 | + """Takes a date-time string in standard ASN1_print form | |
350 | + ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return | |
351 | + a Python time value in seconds past the epoch.""" | |
352 | + | |
353 | + import time | |
354 | + return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT")) | |
355 | + | |
356 | +PEM_HEADER = "-----BEGIN CERTIFICATE-----" | |
357 | +PEM_FOOTER = "-----END CERTIFICATE-----" | |
358 | + | |
359 | +def DER_cert_to_PEM_cert(der_cert_bytes): | |
360 | + | |
361 | + """Takes a certificate in binary DER format and returns the | |
362 | + PEM version of it as a string.""" | |
363 | + | |
364 | + if hasattr(base64, 'standard_b64encode'): | |
365 | + # preferred because older API gets line-length wrong | |
366 | + f = base64.standard_b64encode(der_cert_bytes) | |
367 | + return (PEM_HEADER + '\n' + | |
368 | + textwrap.fill(f, 64) + '\n' + | |
369 | + PEM_FOOTER + '\n') | |
370 | + else: | |
371 | + return (PEM_HEADER + '\n' + | |
372 | + base64.encodestring(der_cert_bytes) + | |
373 | + PEM_FOOTER + '\n') | |
374 | + | |
375 | +def PEM_cert_to_DER_cert(pem_cert_string): | |
376 | + | |
377 | + """Takes a certificate in ASCII PEM format and returns the | |
378 | + DER-encoded version of it as a byte sequence""" | |
379 | + | |
380 | + if not pem_cert_string.startswith(PEM_HEADER): | |
381 | + raise ValueError("Invalid PEM encoding; must start with %s" | |
382 | + % PEM_HEADER) | |
383 | + if not pem_cert_string.strip().endswith(PEM_FOOTER): | |
384 | + raise ValueError("Invalid PEM encoding; must end with %s" | |
385 | + % PEM_FOOTER) | |
386 | + d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] | |
387 | + return base64.decodestring(d) | |
388 | + | |
389 | +def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): | |
390 | + | |
391 | + """Retrieve the certificate from the server at the specified address, | |
392 | + and return it as a PEM-encoded string. | |
393 | + If 'ca_certs' is specified, validate the server cert against it. | |
394 | + If 'ssl_version' is specified, use it in the connection attempt.""" | |
395 | + | |
396 | + host, port = addr | |
397 | + if (ca_certs is not None): | |
398 | + cert_reqs = CERT_REQUIRED | |
399 | + else: | |
400 | + cert_reqs = CERT_NONE | |
401 | + s = wrap_socket(socket(), ssl_version=ssl_version, | |
402 | + cert_reqs=cert_reqs, ca_certs=ca_certs) | |
403 | + s.connect(addr) | |
404 | + dercert = s.getpeercert(True) | |
405 | + s.close() | |
406 | + return DER_cert_to_PEM_cert(dercert) | |
407 | + | |
408 | +def get_protocol_name(protocol_code): | |
409 | + if protocol_code == PROTOCOL_TLSv1: | |
410 | + return "TLSv1" | |
411 | + elif protocol_code == PROTOCOL_SSLv23: | |
412 | + return "SSLv23" | |
413 | + elif protocol_code == PROTOCOL_SSLv2: | |
414 | + return "SSLv2" | |
415 | + elif protocol_code == PROTOCOL_SSLv3: | |
416 | + return "SSLv3" | |
417 | + else: | |
418 | + return "<unknown>" | |
419 | + | |
420 | + | |
421 | +# a replacement for the old socket.ssl function | |
422 | + | |
423 | +def sslwrap_simple(sock, keyfile=None, certfile=None): | |
424 | + | |
425 | + """A replacement for the old socket.ssl function. Designed | |
426 | + for compability with Python 2.5 and earlier. Will disappear in | |
427 | + Python 3.0.""" | |
428 | + | |
429 | + if hasattr(sock, "_sock"): | |
430 | + sock = sock._sock | |
431 | + | |
432 | + ssl_sock = _ssl.sslwrap(sock, 0, keyfile, certfile, CERT_NONE, | |
433 | + PROTOCOL_SSLv23, None) | |
434 | + try: | |
435 | + sock.getpeername() | |
436 | + except socket_error: | |
437 | + # no, no connection yet | |
438 | + pass | |
439 | + else: | |
440 | + # yes, do the handshake | |
441 | + ssl_sock.do_handshake() | |
442 | + | |
443 | + return ssl_sock |
@@ -0,0 +1,1463 @@ | ||
1 | +# subprocess - Subprocesses with accessible I/O streams | |
2 | +# | |
3 | +# For more information about this module, see PEP 324. | |
4 | +# | |
5 | +# This module should remain compatible with Python 2.2, see PEP 291. | |
6 | +# | |
7 | +# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se> | |
8 | +# | |
9 | +# Licensed to PSF under a Contributor Agreement. | |
10 | +# See http://www.python.org/2.4/license for licensing details. | |
11 | + | |
12 | +r"""subprocess - Subprocesses with accessible I/O streams | |
13 | + | |
14 | +This module allows you to spawn processes, connect to their | |
15 | +input/output/error pipes, and obtain their return codes. This module | |
16 | +intends to replace several other, older modules and functions, like: | |
17 | + | |
18 | +os.system | |
19 | +os.spawn* | |
20 | +os.popen* | |
21 | +popen2.* | |
22 | +commands.* | |
23 | + | |
24 | +Information about how the subprocess module can be used to replace these | |
25 | +modules and functions can be found below. | |
26 | + | |
27 | + | |
28 | + | |
29 | +Using the subprocess module | |
30 | +=========================== | |
31 | +This module defines one class called Popen: | |
32 | + | |
33 | +class Popen(args, bufsize=0, executable=None, | |
34 | + stdin=None, stdout=None, stderr=None, | |
35 | + preexec_fn=None, close_fds=False, shell=False, | |
36 | + cwd=None, env=None, universal_newlines=False, | |
37 | + startupinfo=None, creationflags=0): | |
38 | + | |
39 | + | |
40 | +Arguments are: | |
41 | + | |
42 | +args should be a string, or a sequence of program arguments. The | |
43 | +program to execute is normally the first item in the args sequence or | |
44 | +string, but can be explicitly set by using the executable argument. | |
45 | + | |
46 | +On UNIX, with shell=False (default): In this case, the Popen class | |
47 | +uses os.execvp() to execute the child program. args should normally | |
48 | +be a sequence. A string will be treated as a sequence with the string | |
49 | +as the only item (the program to execute). | |
50 | + | |
51 | +On UNIX, with shell=True: If args is a string, it specifies the | |
52 | +command string to execute through the shell. If args is a sequence, | |
53 | +the first item specifies the command string, and any additional items | |
54 | +will be treated as additional shell arguments. | |
55 | + | |
56 | +On Windows: the Popen class uses CreateProcess() to execute the child | |
57 | +program, which operates on strings. If args is a sequence, it will be | |
58 | +converted to a string using the list2cmdline method. Please note that | |
59 | +not all MS Windows applications interpret the command line the same | |
60 | +way: The list2cmdline is designed for applications using the same | |
61 | +rules as the MS C runtime. | |
62 | + | |
63 | +bufsize, if given, has the same meaning as the corresponding argument | |
64 | +to the built-in open() function: 0 means unbuffered, 1 means line | |
65 | +buffered, any other positive value means use a buffer of | |
66 | +(approximately) that size. A negative bufsize means to use the system | |
67 | +default, which usually means fully buffered. The default value for | |
68 | +bufsize is 0 (unbuffered). | |
69 | + | |
70 | +stdin, stdout and stderr specify the executed programs' standard | |
71 | +input, standard output and standard error file handles, respectively. | |
72 | +Valid values are PIPE, an existing file descriptor (a positive | |
73 | +integer), an existing file object, and None. PIPE indicates that a | |
74 | +new pipe to the child should be created. With None, no redirection | |
75 | +will occur; the child's file handles will be inherited from the | |
76 | +parent. Additionally, stderr can be STDOUT, which indicates that the | |
77 | +stderr data from the applications should be captured into the same | |
78 | +file handle as for stdout. | |
79 | + | |
80 | +If preexec_fn is set to a callable object, this object will be called | |
81 | +in the child process just before the child is executed. | |
82 | + | |
83 | +If close_fds is true, all file descriptors except 0, 1 and 2 will be | |
84 | +closed before the child process is executed. | |
85 | + | |
86 | +if shell is true, the specified command will be executed through the | |
87 | +shell. | |
88 | + | |
89 | +If cwd is not None, the current directory will be changed to cwd | |
90 | +before the child is executed. | |
91 | + | |
92 | +If env is not None, it defines the environment variables for the new | |
93 | +process. | |
94 | + | |
95 | +If universal_newlines is true, the file objects stdout and stderr are | |
96 | +opened as a text files, but lines may be terminated by any of '\n', | |
97 | +the Unix end-of-line convention, '\r', the Macintosh convention or | |
98 | +'\r\n', the Windows convention. All of these external representations | |
99 | +are seen as '\n' by the Python program. Note: This feature is only | |
100 | +available if Python is built with universal newline support (the | |
101 | +default). Also, the newlines attribute of the file objects stdout, | |
102 | +stdin and stderr are not updated by the communicate() method. | |
103 | + | |
104 | +The startupinfo and creationflags, if given, will be passed to the | |
105 | +underlying CreateProcess() function. They can specify things such as | |
106 | +appearance of the main window and priority for the new process. | |
107 | +(Windows only) | |
108 | + | |
109 | + | |
110 | +This module also defines some shortcut functions: | |
111 | + | |
112 | +call(*popenargs, **kwargs): | |
113 | + Run command with arguments. Wait for command to complete, then | |
114 | + return the returncode attribute. | |
115 | + | |
116 | + The arguments are the same as for the Popen constructor. Example: | |
117 | + | |
118 | + retcode = call(["ls", "-l"]) | |
119 | + | |
120 | +check_call(*popenargs, **kwargs): | |
121 | + Run command with arguments. Wait for command to complete. If the | |
122 | + exit code was zero then return, otherwise raise | |
123 | + CalledProcessError. The CalledProcessError object will have the | |
124 | + return code in the returncode attribute. | |
125 | + | |
126 | + The arguments are the same as for the Popen constructor. Example: | |
127 | + | |
128 | + check_call(["ls", "-l"]) | |
129 | + | |
130 | +check_output(*popenargs, **kwargs): | |
131 | + Run command with arguments and return its output as a byte string. | |
132 | + | |
133 | + If the exit code was non-zero it raises a CalledProcessError. The | |
134 | + CalledProcessError object will have the return code in the returncode | |
135 | + attribute and output in the output attribute. | |
136 | + | |
137 | + The arguments are the same as for the Popen constructor. Example: | |
138 | + | |
139 | + output = check_output(["ls", "-l", "/dev/null"]) | |
140 | + | |
141 | + | |
142 | +Exceptions | |
143 | +---------- | |
144 | +Exceptions raised in the child process, before the new program has | |
145 | +started to execute, will be re-raised in the parent. Additionally, | |
146 | +the exception object will have one extra attribute called | |
147 | +'child_traceback', which is a string containing traceback information | |
148 | +from the childs point of view. | |
149 | + | |
150 | +The most common exception raised is OSError. This occurs, for | |
151 | +example, when trying to execute a non-existent file. Applications | |
152 | +should prepare for OSErrors. | |
153 | + | |
154 | +A ValueError will be raised if Popen is called with invalid arguments. | |
155 | + | |
156 | +check_call() and check_output() will raise CalledProcessError, if the | |
157 | +called process returns a non-zero return code. | |
158 | + | |
159 | + | |
160 | +Security | |
161 | +-------- | |
162 | +Unlike some other popen functions, this implementation will never call | |
163 | +/bin/sh implicitly. This means that all characters, including shell | |
164 | +metacharacters, can safely be passed to child processes. | |
165 | + | |
166 | + | |
167 | +Popen objects | |
168 | +============= | |
169 | +Instances of the Popen class have the following methods: | |
170 | + | |
171 | +poll() | |
172 | + Check if child process has terminated. Returns returncode | |
173 | + attribute. | |
174 | + | |
175 | +wait() | |
176 | + Wait for child process to terminate. Returns returncode attribute. | |
177 | + | |
178 | +communicate(input=None) | |
179 | + Interact with process: Send data to stdin. Read data from stdout | |
180 | + and stderr, until end-of-file is reached. Wait for process to | |
181 | + terminate. The optional input argument should be a string to be | |
182 | + sent to the child process, or None, if no data should be sent to | |
183 | + the child. | |
184 | + | |
185 | + communicate() returns a tuple (stdout, stderr). | |
186 | + | |
187 | + Note: The data read is buffered in memory, so do not use this | |
188 | + method if the data size is large or unlimited. | |
189 | + | |
190 | +The following attributes are also available: | |
191 | + | |
192 | +stdin | |
193 | + If the stdin argument is PIPE, this attribute is a file object | |
194 | + that provides input to the child process. Otherwise, it is None. | |
195 | + | |
196 | +stdout | |
197 | + If the stdout argument is PIPE, this attribute is a file object | |
198 | + that provides output from the child process. Otherwise, it is | |
199 | + None. | |
200 | + | |
201 | +stderr | |
202 | + If the stderr argument is PIPE, this attribute is file object that | |
203 | + provides error output from the child process. Otherwise, it is | |
204 | + None. | |
205 | + | |
206 | +pid | |
207 | + The process ID of the child process. | |
208 | + | |
209 | +returncode | |
210 | + The child return code. A None value indicates that the process | |
211 | + hasn't terminated yet. A negative value -N indicates that the | |
212 | + child was terminated by signal N (UNIX only). | |
213 | + | |
214 | + | |
215 | +Replacing older functions with the subprocess module | |
216 | +==================================================== | |
217 | +In this section, "a ==> b" means that b can be used as a replacement | |
218 | +for a. | |
219 | + | |
220 | +Note: All functions in this section fail (more or less) silently if | |
221 | +the executed program cannot be found; this module raises an OSError | |
222 | +exception. | |
223 | + | |
224 | +In the following examples, we assume that the subprocess module is | |
225 | +imported with "from subprocess import *". | |
226 | + | |
227 | + | |
228 | +Replacing /bin/sh shell backquote | |
229 | +--------------------------------- | |
230 | +output=`mycmd myarg` | |
231 | +==> | |
232 | +output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] | |
233 | + | |
234 | + | |
235 | +Replacing shell pipe line | |
236 | +------------------------- | |
237 | +output=`dmesg | grep hda` | |
238 | +==> | |
239 | +p1 = Popen(["dmesg"], stdout=PIPE) | |
240 | +p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) | |
241 | +output = p2.communicate()[0] | |
242 | + | |
243 | + | |
244 | +Replacing os.system() | |
245 | +--------------------- | |
246 | +sts = os.system("mycmd" + " myarg") | |
247 | +==> | |
248 | +p = Popen("mycmd" + " myarg", shell=True) | |
249 | +pid, sts = os.waitpid(p.pid, 0) | |
250 | + | |
251 | +Note: | |
252 | + | |
253 | +* Calling the program through the shell is usually not required. | |
254 | + | |
255 | +* It's easier to look at the returncode attribute than the | |
256 | + exitstatus. | |
257 | + | |
258 | +A more real-world example would look like this: | |
259 | + | |
260 | +try: | |
261 | + retcode = call("mycmd" + " myarg", shell=True) | |
262 | + if retcode < 0: | |
263 | + print >>sys.stderr, "Child was terminated by signal", -retcode | |
264 | + else: | |
265 | + print >>sys.stderr, "Child returned", retcode | |
266 | +except OSError, e: | |
267 | + print >>sys.stderr, "Execution failed:", e | |
268 | + | |
269 | + | |
270 | +Replacing os.spawn* | |
271 | +------------------- | |
272 | +P_NOWAIT example: | |
273 | + | |
274 | +pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") | |
275 | +==> | |
276 | +pid = Popen(["/bin/mycmd", "myarg"]).pid | |
277 | + | |
278 | + | |
279 | +P_WAIT example: | |
280 | + | |
281 | +retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") | |
282 | +==> | |
283 | +retcode = call(["/bin/mycmd", "myarg"]) | |
284 | + | |
285 | + | |
286 | +Vector example: | |
287 | + | |
288 | +os.spawnvp(os.P_NOWAIT, path, args) | |
289 | +==> | |
290 | +Popen([path] + args[1:]) | |
291 | + | |
292 | + | |
293 | +Environment example: | |
294 | + | |
295 | +os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) | |
296 | +==> | |
297 | +Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) | |
298 | + | |
299 | + | |
300 | +Replacing os.popen* | |
301 | +------------------- | |
302 | +pipe = os.popen("cmd", mode='r', bufsize) | |
303 | +==> | |
304 | +pipe = Popen("cmd", shell=True, bufsize=bufsize, stdout=PIPE).stdout | |
305 | + | |
306 | +pipe = os.popen("cmd", mode='w', bufsize) | |
307 | +==> | |
308 | +pipe = Popen("cmd", shell=True, bufsize=bufsize, stdin=PIPE).stdin | |
309 | + | |
310 | + | |
311 | +(child_stdin, child_stdout) = os.popen2("cmd", mode, bufsize) | |
312 | +==> | |
313 | +p = Popen("cmd", shell=True, bufsize=bufsize, | |
314 | + stdin=PIPE, stdout=PIPE, close_fds=True) | |
315 | +(child_stdin, child_stdout) = (p.stdin, p.stdout) | |
316 | + | |
317 | + | |
318 | +(child_stdin, | |
319 | + child_stdout, | |
320 | + child_stderr) = os.popen3("cmd", mode, bufsize) | |
321 | +==> | |
322 | +p = Popen("cmd", shell=True, bufsize=bufsize, | |
323 | + stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) | |
324 | +(child_stdin, | |
325 | + child_stdout, | |
326 | + child_stderr) = (p.stdin, p.stdout, p.stderr) | |
327 | + | |
328 | + | |
329 | +(child_stdin, child_stdout_and_stderr) = os.popen4("cmd", mode, | |
330 | + bufsize) | |
331 | +==> | |
332 | +p = Popen("cmd", shell=True, bufsize=bufsize, | |
333 | + stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) | |
334 | +(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) | |
335 | + | |
336 | +On Unix, os.popen2, os.popen3 and os.popen4 also accept a sequence as | |
337 | +the command to execute, in which case arguments will be passed | |
338 | +directly to the program without shell intervention. This usage can be | |
339 | +replaced as follows: | |
340 | + | |
341 | +(child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode, | |
342 | + bufsize) | |
343 | +==> | |
344 | +p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE) | |
345 | +(child_stdin, child_stdout) = (p.stdin, p.stdout) | |
346 | + | |
347 | +Return code handling translates as follows: | |
348 | + | |
349 | +pipe = os.popen("cmd", 'w') | |
350 | +... | |
351 | +rc = pipe.close() | |
352 | +if rc is not None and rc % 256: | |
353 | + print "There were some errors" | |
354 | +==> | |
355 | +process = Popen("cmd", 'w', shell=True, stdin=PIPE) | |
356 | +... | |
357 | +process.stdin.close() | |
358 | +if process.wait() != 0: | |
359 | + print "There were some errors" | |
360 | + | |
361 | + | |
362 | +Replacing popen2.* | |
363 | +------------------ | |
364 | +(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) | |
365 | +==> | |
366 | +p = Popen(["somestring"], shell=True, bufsize=bufsize | |
367 | + stdin=PIPE, stdout=PIPE, close_fds=True) | |
368 | +(child_stdout, child_stdin) = (p.stdout, p.stdin) | |
369 | + | |
370 | +On Unix, popen2 also accepts a sequence as the command to execute, in | |
371 | +which case arguments will be passed directly to the program without | |
372 | +shell intervention. This usage can be replaced as follows: | |
373 | + | |
374 | +(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, | |
375 | + mode) | |
376 | +==> | |
377 | +p = Popen(["mycmd", "myarg"], bufsize=bufsize, | |
378 | + stdin=PIPE, stdout=PIPE, close_fds=True) | |
379 | +(child_stdout, child_stdin) = (p.stdout, p.stdin) | |
380 | + | |
381 | +The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen, | |
382 | +except that: | |
383 | + | |
384 | +* subprocess.Popen raises an exception if the execution fails | |
385 | +* the capturestderr argument is replaced with the stderr argument. | |
386 | +* stdin=PIPE and stdout=PIPE must be specified. | |
387 | +* popen2 closes all filedescriptors by default, but you have to specify | |
388 | + close_fds=True with subprocess.Popen. | |
389 | +""" | |
390 | + | |
391 | +import sys, os | |
392 | +mswindows = (sys.platform == "win32" or (sys.platform == "cli" and os.name == 'nt')) | |
393 | + | |
394 | +import os | |
395 | +import types | |
396 | +import traceback | |
397 | +import gc | |
398 | +import signal | |
399 | + | |
400 | +# Exception classes used by this module. | |
401 | +class CalledProcessError(Exception): | |
402 | + """This exception is raised when a process run by check_call() or | |
403 | + check_output() returns a non-zero exit status. | |
404 | + The exit status will be stored in the returncode attribute; | |
405 | + check_output() will also store the output in the output attribute. | |
406 | + """ | |
407 | + def __init__(self, returncode, cmd, output=None): | |
408 | + self.returncode = returncode | |
409 | + self.cmd = cmd | |
410 | + self.output = output | |
411 | + def __str__(self): | |
412 | + return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) | |
413 | + | |
414 | + | |
415 | +if mswindows: | |
416 | + import threading | |
417 | + import msvcrt | |
418 | + import _subprocess | |
419 | + class STARTUPINFO: | |
420 | + dwFlags = 0 | |
421 | + hStdInput = None | |
422 | + hStdOutput = None | |
423 | + hStdError = None | |
424 | + wShowWindow = 0 | |
425 | + class pywintypes: | |
426 | + error = IOError | |
427 | +else: | |
428 | + import select | |
429 | + _has_poll = hasattr(select, 'poll') | |
430 | + import errno | |
431 | + import fcntl | |
432 | + import pickle | |
433 | + | |
434 | + # When select or poll has indicated that the file is writable, | |
435 | + # we can write up to _PIPE_BUF bytes without risk of blocking. | |
436 | + # POSIX defines PIPE_BUF as >= 512. | |
437 | + _PIPE_BUF = getattr(select, 'PIPE_BUF', 512) | |
438 | + | |
439 | + | |
440 | +__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", | |
441 | + "check_output", "CalledProcessError"] | |
442 | + | |
443 | +if mswindows: | |
444 | + from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP | |
445 | + __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"]) | |
446 | +try: | |
447 | + MAXFD = os.sysconf("SC_OPEN_MAX") | |
448 | +except: | |
449 | + MAXFD = 256 | |
450 | + | |
451 | +_active = [] | |
452 | + | |
453 | +def _cleanup(): | |
454 | + for inst in _active[:]: | |
455 | + res = inst._internal_poll(_deadstate=sys.maxint) | |
456 | + if res is not None and res >= 0: | |
457 | + try: | |
458 | + _active.remove(inst) | |
459 | + except ValueError: | |
460 | + # This can happen if two threads create a new Popen instance. | |
461 | + # It's harmless that it was already removed, so ignore. | |
462 | + pass | |
463 | + else: | |
464 | + print inst.args | |
465 | + | |
466 | +PIPE = -1 | |
467 | +STDOUT = -2 | |
468 | + | |
469 | + | |
470 | +def _eintr_retry_call(func, *args): | |
471 | + while True: | |
472 | + try: | |
473 | + return func(*args) | |
474 | + except OSError, e: | |
475 | + if e.errno == errno.EINTR: | |
476 | + continue | |
477 | + raise | |
478 | + | |
479 | + | |
480 | +def call(*popenargs, **kwargs): | |
481 | + """Run command with arguments. Wait for command to complete, then | |
482 | + return the returncode attribute. | |
483 | + | |
484 | + The arguments are the same as for the Popen constructor. Example: | |
485 | + | |
486 | + retcode = call(["ls", "-l"]) | |
487 | + """ | |
488 | + return Popen(*popenargs, **kwargs).wait() | |
489 | + | |
490 | + | |
491 | +def check_call(*popenargs, **kwargs): | |
492 | + """Run command with arguments. Wait for command to complete. If | |
493 | + the exit code was zero then return, otherwise raise | |
494 | + CalledProcessError. The CalledProcessError object will have the | |
495 | + return code in the returncode attribute. | |
496 | + | |
497 | + The arguments are the same as for the Popen constructor. Example: | |
498 | + | |
499 | + check_call(["ls", "-l"]) | |
500 | + """ | |
501 | + retcode = call(*popenargs, **kwargs) | |
502 | + if retcode: | |
503 | + cmd = kwargs.get("args") | |
504 | + if cmd is None: | |
505 | + cmd = popenargs[0] | |
506 | + raise CalledProcessError(retcode, cmd) | |
507 | + return 0 | |
508 | + | |
509 | + | |
510 | +def check_output(*popenargs, **kwargs): | |
511 | + r"""Run command with arguments and return its output as a byte string. | |
512 | + | |
513 | + If the exit code was non-zero it raises a CalledProcessError. The | |
514 | + CalledProcessError object will have the return code in the returncode | |
515 | + attribute and output in the output attribute. | |
516 | + | |
517 | + The arguments are the same as for the Popen constructor. Example: | |
518 | + | |
519 | + >>> check_output(["ls", "-l", "/dev/null"]) | |
520 | + 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' | |
521 | + | |
522 | + The stdout argument is not allowed as it is used internally. | |
523 | + To capture standard error in the result, use stderr=STDOUT. | |
524 | + | |
525 | + >>> check_output(["/bin/sh", "-c", | |
526 | + ... "ls -l non_existent_file ; exit 0"], | |
527 | + ... stderr=STDOUT) | |
528 | + 'ls: non_existent_file: No such file or directory\n' | |
529 | + """ | |
530 | + if 'stdout' in kwargs: | |
531 | + raise ValueError('stdout argument not allowed, it will be overridden.') | |
532 | + process = Popen(stdout=PIPE, *popenargs, **kwargs) | |
533 | + output, unused_err = process.communicate() | |
534 | + retcode = process.poll() | |
535 | + if retcode: | |
536 | + cmd = kwargs.get("args") | |
537 | + if cmd is None: | |
538 | + cmd = popenargs[0] | |
539 | + raise CalledProcessError(retcode, cmd, output=output) | |
540 | + return output | |
541 | + | |
542 | + | |
543 | +def list2cmdline(seq): | |
544 | + """ | |
545 | + Translate a sequence of arguments into a command line | |
546 | + string, using the same rules as the MS C runtime: | |
547 | + | |
548 | + 1) Arguments are delimited by white space, which is either a | |
549 | + space or a tab. | |
550 | + | |
551 | + 2) A string surrounded by double quotation marks is | |
552 | + interpreted as a single argument, regardless of white space | |
553 | + contained within. A quoted string can be embedded in an | |
554 | + argument. | |
555 | + | |
556 | + 3) A double quotation mark preceded by a backslash is | |
557 | + interpreted as a literal double quotation mark. | |
558 | + | |
559 | + 4) Backslashes are interpreted literally, unless they | |
560 | + immediately precede a double quotation mark. | |
561 | + | |
562 | + 5) If backslashes immediately precede a double quotation mark, | |
563 | + every pair of backslashes is interpreted as a literal | |
564 | + backslash. If the number of backslashes is odd, the last | |
565 | + backslash escapes the next double quotation mark as | |
566 | + described in rule 3. | |
567 | + """ | |
568 | + | |
569 | + # See | |
570 | + # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx | |
571 | + # or search http://msdn.microsoft.com for | |
572 | + # "Parsing C++ Command-Line Arguments" | |
573 | + result = [] | |
574 | + needquote = False | |
575 | + for arg in seq: | |
576 | + bs_buf = [] | |
577 | + | |
578 | + # Add a space to separate this argument from the others | |
579 | + if result: | |
580 | + result.append(' ') | |
581 | + | |
582 | + needquote = (" " in arg) or ("\t" in arg) or not arg | |
583 | + if needquote: | |
584 | + result.append('"') | |
585 | + | |
586 | + for c in arg: | |
587 | + if c == '\\': | |
588 | + # Don't know if we need to double yet. | |
589 | + bs_buf.append(c) | |
590 | + elif c == '"': | |
591 | + # Double backslashes. | |
592 | + result.append('\\' * len(bs_buf)*2) | |
593 | + bs_buf = [] | |
594 | + result.append('\\"') | |
595 | + else: | |
596 | + # Normal char | |
597 | + if bs_buf: | |
598 | + result.extend(bs_buf) | |
599 | + bs_buf = [] | |
600 | + result.append(c) | |
601 | + | |
602 | + # Add remaining backslashes, if any. | |
603 | + if bs_buf: | |
604 | + result.extend(bs_buf) | |
605 | + | |
606 | + if needquote: | |
607 | + result.extend(bs_buf) | |
608 | + result.append('"') | |
609 | + | |
610 | + return ''.join(result) | |
611 | + | |
612 | + | |
613 | +class Popen(object): | |
614 | + def __init__(self, args, bufsize=0, executable=None, | |
615 | + stdin=None, stdout=None, stderr=None, | |
616 | + preexec_fn=None, close_fds=False, shell=False, | |
617 | + cwd=None, env=None, universal_newlines=False, | |
618 | + startupinfo=None, creationflags=0): | |
619 | + """Create new Popen instance.""" | |
620 | + _cleanup() | |
621 | + self.args = args | |
622 | + self._child_created = False | |
623 | + if not isinstance(bufsize, (int, long)): | |
624 | + raise TypeError("bufsize must be an integer") | |
625 | + | |
626 | + if mswindows: | |
627 | + if preexec_fn is not None: | |
628 | + raise ValueError("preexec_fn is not supported on Windows " | |
629 | + "platforms") | |
630 | + if close_fds and (stdin is not None or stdout is not None or | |
631 | + stderr is not None): | |
632 | + raise ValueError("close_fds is not supported on Windows " | |
633 | + "platforms if you redirect stdin/stdout/stderr") | |
634 | + else: | |
635 | + # POSIX | |
636 | + if startupinfo is not None: | |
637 | + raise ValueError("startupinfo is only supported on Windows " | |
638 | + "platforms") | |
639 | + if creationflags != 0: | |
640 | + raise ValueError("creationflags is only supported on Windows " | |
641 | + "platforms") | |
642 | + | |
643 | + self.stdin = None | |
644 | + self.stdout = None | |
645 | + self.stderr = None | |
646 | + self.pid = None | |
647 | + self.returncode = None | |
648 | + self.universal_newlines = universal_newlines | |
649 | + | |
650 | + # Input and output objects. The general principle is like | |
651 | + # this: | |
652 | + # | |
653 | + # Parent Child | |
654 | + # ------ ----- | |
655 | + # p2cwrite ---stdin---> p2cread | |
656 | + # c2pread <--stdout--- c2pwrite | |
657 | + # errread <--stderr--- errwrite | |
658 | + # | |
659 | + # On POSIX, the child objects are file descriptors. On | |
660 | + # Windows, these are Windows file handles. The parent objects | |
661 | + # are file descriptors on both platforms. The parent objects | |
662 | + # are None when not using PIPEs. The child objects are None | |
663 | + # when not redirecting. | |
664 | + | |
665 | + (p2cread, p2cwrite, | |
666 | + c2pread, c2pwrite, | |
667 | + errread, errwrite) = self._get_handles(stdin, stdout, stderr) | |
668 | + | |
669 | + self._execute_child(args, executable, preexec_fn, close_fds, | |
670 | + cwd, env, universal_newlines, | |
671 | + startupinfo, creationflags, shell, | |
672 | + p2cread, p2cwrite, | |
673 | + c2pread, c2pwrite, | |
674 | + errread, errwrite) | |
675 | + | |
676 | + if mswindows: | |
677 | + if p2cwrite is not None: | |
678 | + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) | |
679 | + if c2pread is not None: | |
680 | + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) | |
681 | + if errread is not None: | |
682 | + errread = msvcrt.open_osfhandle(errread.Detach(), 0) | |
683 | + | |
684 | + if p2cwrite is not None: | |
685 | + self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) | |
686 | + if c2pread is not None: | |
687 | + if universal_newlines: | |
688 | + self.stdout = os.fdopen(c2pread, 'rU', bufsize) | |
689 | + else: | |
690 | + self.stdout = os.fdopen(c2pread, 'rb', bufsize) | |
691 | + if errread is not None: | |
692 | + if universal_newlines: | |
693 | + self.stderr = os.fdopen(errread, 'rU', bufsize) | |
694 | + else: | |
695 | + self.stderr = os.fdopen(errread, 'rb', bufsize) | |
696 | + | |
697 | + | |
698 | + def _translate_newlines(self, data): | |
699 | + data = data.replace("\r\n", "\n") | |
700 | + data = data.replace("\r", "\n") | |
701 | + return data | |
702 | + | |
703 | + | |
704 | + def __del__(self, _maxint=sys.maxint, _active=_active): | |
705 | + if not self._child_created: | |
706 | + # We didn't get to successfully create a child process. | |
707 | + return | |
708 | + # In case the child hasn't been waited on, check if it's done. | |
709 | + self._internal_poll(_deadstate=_maxint) | |
710 | + if self.returncode is None and _active is not None: | |
711 | + # Child is still running, keep us alive until we can wait on it. | |
712 | + _active.append(self) | |
713 | + | |
714 | + | |
715 | + def communicate(self, input=None): | |
716 | + """Interact with process: Send data to stdin. Read data from | |
717 | + stdout and stderr, until end-of-file is reached. Wait for | |
718 | + process to terminate. The optional input argument should be a | |
719 | + string to be sent to the child process, or None, if no data | |
720 | + should be sent to the child. | |
721 | + | |
722 | + communicate() returns a tuple (stdout, stderr).""" | |
723 | + | |
724 | + # Optimization: If we are only using one pipe, or no pipe at | |
725 | + # all, using select() or threads is unnecessary. | |
726 | + if [self.stdin, self.stdout, self.stderr].count(None) >= 2: | |
727 | + stdout = None | |
728 | + stderr = None | |
729 | + if self.stdin: | |
730 | + if input: | |
731 | + self.stdin.write(input) | |
732 | + self.stdin.close() | |
733 | + elif self.stdout: | |
734 | + stdout = self.stdout.read() | |
735 | + self.stdout.close() | |
736 | + elif self.stderr: | |
737 | + stderr = self.stderr.read() | |
738 | + self.stderr.close() | |
739 | + self.wait() | |
740 | + return (stdout, stderr) | |
741 | + | |
742 | + return self._communicate(input) | |
743 | + | |
744 | + | |
745 | + def poll(self): | |
746 | + return self._internal_poll() | |
747 | + | |
748 | + | |
749 | + if mswindows: | |
750 | + # | |
751 | + # Windows methods | |
752 | + # | |
753 | + def _get_handles(self, stdin, stdout, stderr): | |
754 | + """Construct and return tuple with IO objects: | |
755 | + p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite | |
756 | + """ | |
757 | + if stdin is None and stdout is None and stderr is None: | |
758 | + return (None, None, None, None, None, None) | |
759 | + | |
760 | + p2cread, p2cwrite = None, None | |
761 | + c2pread, c2pwrite = None, None | |
762 | + errread, errwrite = None, None | |
763 | + | |
764 | + if stdin is None: | |
765 | + p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE) | |
766 | + if p2cread is None: | |
767 | + p2cread, _ = _subprocess.CreatePipe(None, 0) | |
768 | + elif stdin == PIPE: | |
769 | + p2cread, p2cwrite = _subprocess.CreatePipe(None, 0) | |
770 | + elif isinstance(stdin, int): | |
771 | + p2cread = msvcrt.get_osfhandle(stdin) | |
772 | + else: | |
773 | + # Assuming file-like object | |
774 | + p2cread = msvcrt.get_osfhandle(stdin.fileno()) | |
775 | + p2cread = self._make_inheritable(p2cread) | |
776 | + | |
777 | + if stdout is None: | |
778 | + c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE) | |
779 | + if c2pwrite is None: | |
780 | + _, c2pwrite = _subprocess.CreatePipe(None, 0) | |
781 | + elif stdout == PIPE: | |
782 | + c2pread, c2pwrite = _subprocess.CreatePipe(None, 0) | |
783 | + elif isinstance(stdout, int): | |
784 | + c2pwrite = msvcrt.get_osfhandle(stdout) | |
785 | + else: | |
786 | + # Assuming file-like object | |
787 | + c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) | |
788 | + c2pwrite = self._make_inheritable(c2pwrite) | |
789 | + | |
790 | + if stderr is None: | |
791 | + errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE) | |
792 | + if errwrite is None: | |
793 | + _, errwrite = _subprocess.CreatePipe(None, 0) | |
794 | + elif stderr == PIPE: | |
795 | + errread, errwrite = _subprocess.CreatePipe(None, 0) | |
796 | + elif stderr == STDOUT: | |
797 | + errwrite = c2pwrite | |
798 | + elif isinstance(stderr, int): | |
799 | + errwrite = msvcrt.get_osfhandle(stderr) | |
800 | + else: | |
801 | + # Assuming file-like object | |
802 | + errwrite = msvcrt.get_osfhandle(stderr.fileno()) | |
803 | + errwrite = self._make_inheritable(errwrite) | |
804 | + | |
805 | + return (p2cread, p2cwrite, | |
806 | + c2pread, c2pwrite, | |
807 | + errread, errwrite) | |
808 | + | |
809 | + | |
810 | + def _make_inheritable(self, handle): | |
811 | + """Return a duplicate of handle, which is inheritable""" | |
812 | + return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), | |
813 | + handle, _subprocess.GetCurrentProcess(), 0, 1, | |
814 | + _subprocess.DUPLICATE_SAME_ACCESS) | |
815 | + | |
816 | + | |
817 | + def _find_w9xpopen(self): | |
818 | + """Find and return absolut path to w9xpopen.exe""" | |
819 | + w9xpopen = os.path.join( | |
820 | + os.path.dirname(_subprocess.GetModuleFileName(0)), | |
821 | + "w9xpopen.exe") | |
822 | + if not os.path.exists(w9xpopen): | |
823 | + # Eeek - file-not-found - possibly an embedding | |
824 | + # situation - see if we can locate it in sys.exec_prefix | |
825 | + w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), | |
826 | + "w9xpopen.exe") | |
827 | + if not os.path.exists(w9xpopen): | |
828 | + raise RuntimeError("Cannot locate w9xpopen.exe, which is " | |
829 | + "needed for Popen to work with your " | |
830 | + "shell or platform.") | |
831 | + return w9xpopen | |
832 | + | |
833 | + | |
834 | + def _execute_child(self, args, executable, preexec_fn, close_fds, | |
835 | + cwd, env, universal_newlines, | |
836 | + startupinfo, creationflags, shell, | |
837 | + p2cread, p2cwrite, | |
838 | + c2pread, c2pwrite, | |
839 | + errread, errwrite): | |
840 | + """Execute program (MS Windows version)""" | |
841 | + | |
842 | + if not isinstance(args, types.StringTypes): | |
843 | + args = list2cmdline(args) | |
844 | + | |
845 | + # Process startup details | |
846 | + if startupinfo is None: | |
847 | + startupinfo = STARTUPINFO() | |
848 | + if None not in (p2cread, c2pwrite, errwrite): | |
849 | + startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES | |
850 | + startupinfo.hStdInput = p2cread | |
851 | + startupinfo.hStdOutput = c2pwrite | |
852 | + startupinfo.hStdError = errwrite | |
853 | + | |
854 | + if shell: | |
855 | + startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW | |
856 | + startupinfo.wShowWindow = _subprocess.SW_HIDE | |
857 | + comspec = os.environ.get("COMSPEC", "cmd.exe") | |
858 | + args = comspec + " /c " + args | |
859 | + if (_subprocess.GetVersion() >= 0x80000000L or | |
860 | + os.path.basename(comspec).lower() == "command.com"): | |
861 | + # Win9x, or using command.com on NT. We need to | |
862 | + # use the w9xpopen intermediate program. For more | |
863 | + # information, see KB Q150956 | |
864 | + # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) | |
865 | + w9xpopen = self._find_w9xpopen() | |
866 | + args = '"%s" %s' % (w9xpopen, args) | |
867 | + # Not passing CREATE_NEW_CONSOLE has been known to | |
868 | + # cause random failures on win9x. Specifically a | |
869 | + # dialog: "Your program accessed mem currently in | |
870 | + # use at xxx" and a hopeful warning about the | |
871 | + # stability of your system. Cost is Ctrl+C wont | |
872 | + # kill children. | |
873 | + creationflags |= _subprocess.CREATE_NEW_CONSOLE | |
874 | + | |
875 | + # Start the process | |
876 | + try: | |
877 | + hp, ht, pid, tid = _subprocess.CreateProcess(executable, args, | |
878 | + # no special security | |
879 | + None, None, | |
880 | + int(not close_fds), | |
881 | + creationflags, | |
882 | + env, | |
883 | + cwd, | |
884 | + startupinfo) | |
885 | + except pywintypes.error, e: | |
886 | + # Translate pywintypes.error to WindowsError, which is | |
887 | + # a subclass of OSError. FIXME: We should really | |
888 | + # translate errno using _sys_errlist (or simliar), but | |
889 | + # how can this be done from Python? | |
890 | + raise WindowsError(*e.args) | |
891 | + | |
892 | + # Retain the process handle, but close the thread handle | |
893 | + self._child_created = True | |
894 | + self._handle = hp | |
895 | + self.pid = pid | |
896 | + ht.Close() | |
897 | + | |
898 | + # Child is launched. Close the parent's copy of those pipe | |
899 | + # handles that only the child should have open. You need | |
900 | + # to make sure that no handles to the write end of the | |
901 | + # output pipe are maintained in this process or else the | |
902 | + # pipe will not close when the child process exits and the | |
903 | + # ReadFile will hang. | |
904 | + if p2cread is not None: | |
905 | + p2cread.Close() | |
906 | + if c2pwrite is not None: | |
907 | + c2pwrite.Close() | |
908 | + if errwrite is not None: | |
909 | + errwrite.Close() | |
910 | + | |
911 | + | |
912 | + def _internal_poll(self, _deadstate=None, | |
913 | + _WaitForSingleObject=_subprocess.WaitForSingleObject, | |
914 | + _WAIT_OBJECT_0=_subprocess.WAIT_OBJECT_0, | |
915 | + _GetExitCodeProcess=_subprocess.GetExitCodeProcess): | |
916 | + """Check if child process has terminated. Returns returncode | |
917 | + attribute. | |
918 | + | |
919 | + This method is called by __del__, so it can only refer to objects | |
920 | + in its local scope. | |
921 | + | |
922 | + """ | |
923 | + if self.returncode is None: | |
924 | + if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0: | |
925 | + self.returncode = _GetExitCodeProcess(self._handle) | |
926 | + return self.returncode | |
927 | + | |
928 | + | |
929 | + def wait(self): | |
930 | + """Wait for child process to terminate. Returns returncode | |
931 | + attribute.""" | |
932 | + if self.returncode is None: | |
933 | + _subprocess.WaitForSingleObject(self._handle, | |
934 | + _subprocess.INFINITE) | |
935 | + self.returncode = _subprocess.GetExitCodeProcess(self._handle) | |
936 | + return self.returncode | |
937 | + | |
938 | + | |
939 | + def _readerthread(self, fh, buffer): | |
940 | + buffer.append(fh.read()) | |
941 | + | |
942 | + | |
943 | + def _communicate(self, input): | |
944 | + stdout = None # Return | |
945 | + stderr = None # Return | |
946 | + | |
947 | + if self.stdout: | |
948 | + stdout = [] | |
949 | + stdout_thread = threading.Thread(target=self._readerthread, | |
950 | + args=(self.stdout, stdout)) | |
951 | + stdout_thread.setDaemon(True) | |
952 | + stdout_thread.start() | |
953 | + if self.stderr: | |
954 | + stderr = [] | |
955 | + stderr_thread = threading.Thread(target=self._readerthread, | |
956 | + args=(self.stderr, stderr)) | |
957 | + stderr_thread.setDaemon(True) | |
958 | + stderr_thread.start() | |
959 | + | |
960 | + if self.stdin: | |
961 | + if input is not None: | |
962 | + self.stdin.write(input) | |
963 | + self.stdin.close() | |
964 | + | |
965 | + if self.stdout: | |
966 | + stdout_thread.join() | |
967 | + if self.stderr: | |
968 | + stderr_thread.join() | |
969 | + | |
970 | + # All data exchanged. Translate lists into strings. | |
971 | + if stdout is not None: | |
972 | + stdout = stdout[0] | |
973 | + if stderr is not None: | |
974 | + stderr = stderr[0] | |
975 | + | |
976 | + # Translate newlines, if requested. We cannot let the file | |
977 | + # object do the translation: It is based on stdio, which is | |
978 | + # impossible to combine with select (unless forcing no | |
979 | + # buffering). | |
980 | + if self.universal_newlines and hasattr(file, 'newlines'): | |
981 | + if stdout: | |
982 | + stdout = self._translate_newlines(stdout) | |
983 | + if stderr: | |
984 | + stderr = self._translate_newlines(stderr) | |
985 | + | |
986 | + self.wait() | |
987 | + return (stdout, stderr) | |
988 | + | |
989 | + def send_signal(self, sig): | |
990 | + """Send a signal to the process | |
991 | + """ | |
992 | + if sig == signal.SIGTERM: | |
993 | + self.terminate() | |
994 | + elif sig == signal.CTRL_C_EVENT: | |
995 | + os.kill(self.pid, signal.CTRL_C_EVENT) | |
996 | + elif sig == signal.CTRL_BREAK_EVENT: | |
997 | + os.kill(self.pid, signal.CTRL_BREAK_EVENT) | |
998 | + else: | |
999 | + raise ValueError("Only SIGTERM is supported on Windows") | |
1000 | + | |
1001 | + def terminate(self): | |
1002 | + """Terminates the process | |
1003 | + """ | |
1004 | + _subprocess.TerminateProcess(self._handle, 1) | |
1005 | + | |
1006 | + kill = terminate | |
1007 | + | |
1008 | + else: | |
1009 | + # | |
1010 | + # POSIX methods | |
1011 | + # | |
1012 | + def _get_handles(self, stdin, stdout, stderr): | |
1013 | + """Construct and return tuple with IO objects: | |
1014 | + p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite | |
1015 | + """ | |
1016 | + p2cread, p2cwrite = None, None | |
1017 | + c2pread, c2pwrite = None, None | |
1018 | + errread, errwrite = None, None | |
1019 | + | |
1020 | + if stdin is None: | |
1021 | + pass | |
1022 | + elif stdin == PIPE: | |
1023 | + p2cread, p2cwrite = os.pipe() | |
1024 | + elif isinstance(stdin, int): | |
1025 | + p2cread = stdin | |
1026 | + else: | |
1027 | + # Assuming file-like object | |
1028 | + p2cread = stdin.fileno() | |
1029 | + | |
1030 | + if stdout is None: | |
1031 | + pass | |
1032 | + elif stdout == PIPE: | |
1033 | + c2pread, c2pwrite = os.pipe() | |
1034 | + elif isinstance(stdout, int): | |
1035 | + c2pwrite = stdout | |
1036 | + else: | |
1037 | + # Assuming file-like object | |
1038 | + c2pwrite = stdout.fileno() | |
1039 | + | |
1040 | + if stderr is None: | |
1041 | + pass | |
1042 | + elif stderr == PIPE: | |
1043 | + errread, errwrite = os.pipe() | |
1044 | + elif stderr == STDOUT: | |
1045 | + errwrite = c2pwrite | |
1046 | + elif isinstance(stderr, int): | |
1047 | + errwrite = stderr | |
1048 | + else: | |
1049 | + # Assuming file-like object | |
1050 | + errwrite = stderr.fileno() | |
1051 | + | |
1052 | + return (p2cread, p2cwrite, | |
1053 | + c2pread, c2pwrite, | |
1054 | + errread, errwrite) | |
1055 | + | |
1056 | + | |
1057 | + def _set_cloexec_flag(self, fd): | |
1058 | + try: | |
1059 | + cloexec_flag = fcntl.FD_CLOEXEC | |
1060 | + except AttributeError: | |
1061 | + cloexec_flag = 1 | |
1062 | + | |
1063 | + old = fcntl.fcntl(fd, fcntl.F_GETFD) | |
1064 | + fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) | |
1065 | + | |
1066 | + | |
1067 | + def _close_fds(self, but): | |
1068 | + if hasattr(os, 'closerange'): | |
1069 | + os.closerange(3, but) | |
1070 | + os.closerange(but + 1, MAXFD) | |
1071 | + else: | |
1072 | + for i in xrange(3, MAXFD): | |
1073 | + if i == but: | |
1074 | + continue | |
1075 | + try: | |
1076 | + os.close(i) | |
1077 | + except: | |
1078 | + pass | |
1079 | + | |
1080 | + | |
1081 | + def _execute_child(self, args, executable, preexec_fn, close_fds, | |
1082 | + cwd, env, universal_newlines, | |
1083 | + startupinfo, creationflags, shell, | |
1084 | + p2cread, p2cwrite, | |
1085 | + c2pread, c2pwrite, | |
1086 | + errread, errwrite): | |
1087 | + """Execute program (POSIX version)""" | |
1088 | + | |
1089 | + if isinstance(args, types.StringTypes): | |
1090 | + args = [args] | |
1091 | + else: | |
1092 | + args = list(args) | |
1093 | + | |
1094 | + if shell: | |
1095 | + args = ["/bin/sh", "-c"] + args | |
1096 | + | |
1097 | + if executable is None: | |
1098 | + executable = args[0] | |
1099 | + | |
1100 | + # For transferring possible exec failure from child to parent | |
1101 | + # The first char specifies the exception type: 0 means | |
1102 | + # OSError, 1 means some other error. | |
1103 | + errpipe_read, errpipe_write = os.pipe() | |
1104 | + try: | |
1105 | + try: | |
1106 | + self._set_cloexec_flag(errpipe_write) | |
1107 | + | |
1108 | + gc_was_enabled = gc.isenabled() | |
1109 | + # Disable gc to avoid bug where gc -> file_dealloc -> | |
1110 | + # write to stderr -> hang. http://bugs.python.org/issue1336 | |
1111 | + gc.disable() | |
1112 | + try: | |
1113 | + self.pid = os.fork() | |
1114 | + except: | |
1115 | + if gc_was_enabled: | |
1116 | + gc.enable() | |
1117 | + raise | |
1118 | + self._child_created = True | |
1119 | + if self.pid == 0: | |
1120 | + # Child | |
1121 | + try: | |
1122 | + # Close parent's pipe ends | |
1123 | + if p2cwrite is not None: | |
1124 | + os.close(p2cwrite) | |
1125 | + if c2pread is not None: | |
1126 | + os.close(c2pread) | |
1127 | + if errread is not None: | |
1128 | + os.close(errread) | |
1129 | + os.close(errpipe_read) | |
1130 | + | |
1131 | + # Dup fds for child | |
1132 | + if p2cread is not None: | |
1133 | + os.dup2(p2cread, 0) | |
1134 | + if c2pwrite is not None: | |
1135 | + os.dup2(c2pwrite, 1) | |
1136 | + if errwrite is not None: | |
1137 | + os.dup2(errwrite, 2) | |
1138 | + | |
1139 | + # Close pipe fds. Make sure we don't close the same | |
1140 | + # fd more than once, or standard fds. | |
1141 | + if p2cread is not None and p2cread not in (0,): | |
1142 | + os.close(p2cread) | |
1143 | + if c2pwrite is not None and c2pwrite not in (p2cread, 1): | |
1144 | + os.close(c2pwrite) | |
1145 | + if errwrite is not None and errwrite not in (p2cread, c2pwrite, 2): | |
1146 | + os.close(errwrite) | |
1147 | + | |
1148 | + # Close all other fds, if asked for | |
1149 | + if close_fds: | |
1150 | + self._close_fds(but=errpipe_write) | |
1151 | + | |
1152 | + if cwd is not None: | |
1153 | + os.chdir(cwd) | |
1154 | + | |
1155 | + if preexec_fn: | |
1156 | + preexec_fn() | |
1157 | + | |
1158 | + if env is None: | |
1159 | + os.execvp(executable, args) | |
1160 | + else: | |
1161 | + os.execvpe(executable, args, env) | |
1162 | + | |
1163 | + except: | |
1164 | + exc_type, exc_value, tb = sys.exc_info() | |
1165 | + # Save the traceback and attach it to the exception object | |
1166 | + exc_lines = traceback.format_exception(exc_type, | |
1167 | + exc_value, | |
1168 | + tb) | |
1169 | + exc_value.child_traceback = ''.join(exc_lines) | |
1170 | + os.write(errpipe_write, pickle.dumps(exc_value)) | |
1171 | + | |
1172 | + # This exitcode won't be reported to applications, so it | |
1173 | + # really doesn't matter what we return. | |
1174 | + os._exit(255) | |
1175 | + | |
1176 | + # Parent | |
1177 | + if gc_was_enabled: | |
1178 | + gc.enable() | |
1179 | + finally: | |
1180 | + # be sure the FD is closed no matter what | |
1181 | + os.close(errpipe_write) | |
1182 | + | |
1183 | + if p2cread is not None and p2cwrite is not None: | |
1184 | + os.close(p2cread) | |
1185 | + if c2pwrite is not None and c2pread is not None: | |
1186 | + os.close(c2pwrite) | |
1187 | + if errwrite is not None and errread is not None: | |
1188 | + os.close(errwrite) | |
1189 | + | |
1190 | + # Wait for exec to fail or succeed; possibly raising exception | |
1191 | + # Exception limited to 1M | |
1192 | + data = _eintr_retry_call(os.read, errpipe_read, 1048576) | |
1193 | + finally: | |
1194 | + # be sure the FD is closed no matter what | |
1195 | + os.close(errpipe_read) | |
1196 | + | |
1197 | + if data != "": | |
1198 | + _eintr_retry_call(os.waitpid, self.pid, 0) | |
1199 | + child_exception = pickle.loads(data) | |
1200 | + for fd in (p2cwrite, c2pread, errread): | |
1201 | + if fd is not None: | |
1202 | + os.close(fd) | |
1203 | + raise child_exception | |
1204 | + | |
1205 | + | |
1206 | + def _handle_exitstatus(self, sts, _WIFSIGNALED=os.WIFSIGNALED, | |
1207 | + _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED, | |
1208 | + _WEXITSTATUS=os.WEXITSTATUS): | |
1209 | + # This method is called (indirectly) by __del__, so it cannot | |
1210 | + # refer to anything outside of its local scope.""" | |
1211 | + if _WIFSIGNALED(sts): | |
1212 | + self.returncode = -_WTERMSIG(sts) | |
1213 | + elif _WIFEXITED(sts): | |
1214 | + self.returncode = _WEXITSTATUS(sts) | |
1215 | + else: | |
1216 | + # Should never happen | |
1217 | + raise RuntimeError("Unknown child exit status!") | |
1218 | + | |
1219 | + | |
1220 | + def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid, | |
1221 | + _WNOHANG=os.WNOHANG, _os_error=os.error): | |
1222 | + """Check if child process has terminated. Returns returncode | |
1223 | + attribute. | |
1224 | + | |
1225 | + This method is called by __del__, so it cannot reference anything | |
1226 | + outside of the local scope (nor can any methods it calls). | |
1227 | + | |
1228 | + """ | |
1229 | + if self.returncode is None: | |
1230 | + try: | |
1231 | + pid, sts = _waitpid(self.pid, _WNOHANG) | |
1232 | + if pid == self.pid: | |
1233 | + self._handle_exitstatus(sts) | |
1234 | + except _os_error: | |
1235 | + if _deadstate is not None: | |
1236 | + self.returncode = _deadstate | |
1237 | + return self.returncode | |
1238 | + | |
1239 | + | |
1240 | + def wait(self): | |
1241 | + """Wait for child process to terminate. Returns returncode | |
1242 | + attribute.""" | |
1243 | + if self.returncode is None: | |
1244 | + pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) | |
1245 | + self._handle_exitstatus(sts) | |
1246 | + return self.returncode | |
1247 | + | |
1248 | + | |
1249 | + def _communicate(self, input): | |
1250 | + if self.stdin: | |
1251 | + # Flush stdio buffer. This might block, if the user has | |
1252 | + # been writing to .stdin in an uncontrolled fashion. | |
1253 | + self.stdin.flush() | |
1254 | + if not input: | |
1255 | + self.stdin.close() | |
1256 | + | |
1257 | + if _has_poll: | |
1258 | + stdout, stderr = self._communicate_with_poll(input) | |
1259 | + else: | |
1260 | + stdout, stderr = self._communicate_with_select(input) | |
1261 | + | |
1262 | + # All data exchanged. Translate lists into strings. | |
1263 | + if stdout is not None: | |
1264 | + stdout = ''.join(stdout) | |
1265 | + if stderr is not None: | |
1266 | + stderr = ''.join(stderr) | |
1267 | + | |
1268 | + # Translate newlines, if requested. We cannot let the file | |
1269 | + # object do the translation: It is based on stdio, which is | |
1270 | + # impossible to combine with select (unless forcing no | |
1271 | + # buffering). | |
1272 | + if self.universal_newlines and hasattr(file, 'newlines'): | |
1273 | + if stdout: | |
1274 | + stdout = self._translate_newlines(stdout) | |
1275 | + if stderr: | |
1276 | + stderr = self._translate_newlines(stderr) | |
1277 | + | |
1278 | + self.wait() | |
1279 | + return (stdout, stderr) | |
1280 | + | |
1281 | + | |
1282 | + def _communicate_with_poll(self, input): | |
1283 | + stdout = None # Return | |
1284 | + stderr = None # Return | |
1285 | + fd2file = {} | |
1286 | + fd2output = {} | |
1287 | + | |
1288 | + poller = select.poll() | |
1289 | + def register_and_append(file_obj, eventmask): | |
1290 | + poller.register(file_obj.fileno(), eventmask) | |
1291 | + fd2file[file_obj.fileno()] = file_obj | |
1292 | + | |
1293 | + def close_unregister_and_remove(fd): | |
1294 | + poller.unregister(fd) | |
1295 | + fd2file[fd].close() | |
1296 | + fd2file.pop(fd) | |
1297 | + | |
1298 | + if self.stdin and input: | |
1299 | + register_and_append(self.stdin, select.POLLOUT) | |
1300 | + | |
1301 | + select_POLLIN_POLLPRI = select.POLLIN | select.POLLPRI | |
1302 | + if self.stdout: | |
1303 | + register_and_append(self.stdout, select_POLLIN_POLLPRI) | |
1304 | + fd2output[self.stdout.fileno()] = stdout = [] | |
1305 | + if self.stderr: | |
1306 | + register_and_append(self.stderr, select_POLLIN_POLLPRI) | |
1307 | + fd2output[self.stderr.fileno()] = stderr = [] | |
1308 | + | |
1309 | + input_offset = 0 | |
1310 | + while fd2file: | |
1311 | + try: | |
1312 | + ready = poller.poll() | |
1313 | + except select.error, e: | |
1314 | + if e.args[0] == errno.EINTR: | |
1315 | + continue | |
1316 | + raise | |
1317 | + | |
1318 | + for fd, mode in ready: | |
1319 | + if mode & select.POLLOUT: | |
1320 | + chunk = input[input_offset : input_offset + _PIPE_BUF] | |
1321 | + input_offset += os.write(fd, chunk) | |
1322 | + if input_offset >= len(input): | |
1323 | + close_unregister_and_remove(fd) | |
1324 | + elif mode & select_POLLIN_POLLPRI: | |
1325 | + data = os.read(fd, 4096) | |
1326 | + if not data: | |
1327 | + close_unregister_and_remove(fd) | |
1328 | + fd2output[fd].append(data) | |
1329 | + else: | |
1330 | + # Ignore hang up or errors. | |
1331 | + close_unregister_and_remove(fd) | |
1332 | + | |
1333 | + return (stdout, stderr) | |
1334 | + | |
1335 | + | |
1336 | + def _communicate_with_select(self, input): | |
1337 | + read_set = [] | |
1338 | + write_set = [] | |
1339 | + stdout = None # Return | |
1340 | + stderr = None # Return | |
1341 | + | |
1342 | + if self.stdin and input: | |
1343 | + write_set.append(self.stdin) | |
1344 | + if self.stdout: | |
1345 | + read_set.append(self.stdout) | |
1346 | + stdout = [] | |
1347 | + if self.stderr: | |
1348 | + read_set.append(self.stderr) | |
1349 | + stderr = [] | |
1350 | + | |
1351 | + input_offset = 0 | |
1352 | + while read_set or write_set: | |
1353 | + try: | |
1354 | + rlist, wlist, xlist = select.select(read_set, write_set, []) | |
1355 | + except select.error, e: | |
1356 | + if e.args[0] == errno.EINTR: | |
1357 | + continue | |
1358 | + raise | |
1359 | + | |
1360 | + if self.stdin in wlist: | |
1361 | + chunk = input[input_offset : input_offset + _PIPE_BUF] | |
1362 | + bytes_written = os.write(self.stdin.fileno(), chunk) | |
1363 | + input_offset += bytes_written | |
1364 | + if input_offset >= len(input): | |
1365 | + self.stdin.close() | |
1366 | + write_set.remove(self.stdin) | |
1367 | + | |
1368 | + if self.stdout in rlist: | |
1369 | + data = os.read(self.stdout.fileno(), 1024) | |
1370 | + if data == "": | |
1371 | + self.stdout.close() | |
1372 | + read_set.remove(self.stdout) | |
1373 | + stdout.append(data) | |
1374 | + | |
1375 | + if self.stderr in rlist: | |
1376 | + data = os.read(self.stderr.fileno(), 1024) | |
1377 | + if data == "": | |
1378 | + self.stderr.close() | |
1379 | + read_set.remove(self.stderr) | |
1380 | + stderr.append(data) | |
1381 | + | |
1382 | + return (stdout, stderr) | |
1383 | + | |
1384 | + | |
1385 | + def send_signal(self, sig): | |
1386 | + """Send a signal to the process | |
1387 | + """ | |
1388 | + os.kill(self.pid, sig) | |
1389 | + | |
1390 | + def terminate(self): | |
1391 | + """Terminate the process with SIGTERM | |
1392 | + """ | |
1393 | + self.send_signal(signal.SIGTERM) | |
1394 | + | |
1395 | + def kill(self): | |
1396 | + """Kill the process with SIGKILL | |
1397 | + """ | |
1398 | + self.send_signal(signal.SIGKILL) | |
1399 | + | |
1400 | + | |
1401 | +def _demo_posix(): | |
1402 | + # | |
1403 | + # Example 1: Simple redirection: Get process list | |
1404 | + # | |
1405 | + plist = Popen(["ps"], stdout=PIPE).communicate()[0] | |
1406 | + print "Process list:" | |
1407 | + print plist | |
1408 | + | |
1409 | + # | |
1410 | + # Example 2: Change uid before executing child | |
1411 | + # | |
1412 | + if os.getuid() == 0: | |
1413 | + p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) | |
1414 | + p.wait() | |
1415 | + | |
1416 | + # | |
1417 | + # Example 3: Connecting several subprocesses | |
1418 | + # | |
1419 | + print "Looking for 'hda'..." | |
1420 | + p1 = Popen(["dmesg"], stdout=PIPE) | |
1421 | + p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) | |
1422 | + print repr(p2.communicate()[0]) | |
1423 | + | |
1424 | + # | |
1425 | + # Example 4: Catch execution error | |
1426 | + # | |
1427 | ||
1428 | + print "Trying a weird file..." | |
1429 | + try: | |
1430 | + print Popen(["/this/path/does/not/exist"]).communicate() | |
1431 | + except OSError, e: | |
1432 | + if e.errno == errno.ENOENT: | |
1433 | + print "The file didn't exist. I thought so..." | |
1434 | + print "Child traceback:" | |
1435 | + print e.child_traceback | |
1436 | + else: | |
1437 | + print "Error", e.errno | |
1438 | + else: | |
1439 | + print >>sys.stderr, "Gosh. No error." | |
1440 | + | |
1441 | + | |
1442 | +def _demo_windows(): | |
1443 | + # | |
1444 | + # Example 1: Connecting several subprocesses | |
1445 | + # | |
1446 | + print "Looking for 'PROMPT' in set output..." | |
1447 | + p1 = Popen("set", stdout=PIPE, shell=True) | |
1448 | + p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) | |
1449 | + print repr(p2.communicate()[0]) | |
1450 | + | |
1451 | + # | |
1452 | + # Example 2: Simple execution of program | |
1453 | + # | |
1454 | + print "Executing calc..." | |
1455 | + p = Popen("calc") | |
1456 | + p.wait() | |
1457 | + | |
1458 | + | |
1459 | +if __name__ == "__main__": | |
1460 | + if mswindows: | |
1461 | + _demo_windows() | |
1462 | + else: | |
1463 | + _demo_posix() |
@@ -3,7 +3,7 @@ | ||
3 | 3 | #------------------------------------------------------------------- |
4 | 4 | # tarfile.py |
5 | 5 | #------------------------------------------------------------------- |
6 | -# Copyright (C) 2002 Lars Gust?スbel <lars@gustaebel.de> | |
6 | +# Copyright (C) 2002 Lars Gust臙el <lars@gustaebel.de> | |
7 | 7 | # All rights reserved. |
8 | 8 | # |
9 | 9 | # Permission is hereby granted, free of charge, to any person |
@@ -34,10 +34,10 @@ __version__ = "$Revision: 81667 $" | ||
34 | 34 | # $Source$ |
35 | 35 | |
36 | 36 | version = "0.9.0" |
37 | -__author__ = "Lars Gust?スbel (lars@gustaebel.de)" | |
37 | +__author__ = "Lars Gust臙el (lars@gustaebel.de)" | |
38 | 38 | __date__ = "$Date: 2010-06-03 14:34:14 +0200 (Do, 03 Jun 2010) $" |
39 | 39 | __cvsid__ = "$Id: tarfile.py 81667 2010-06-03 12:34:14Z lars.gustaebel $" |
40 | -__credits__ = "Gustavo Niemeyer, Niels Gust?スbel, Richard Townsend." | |
40 | +__credits__ = "Gustavo Niemeyer, Niels Gust臙el, Richard Townsend." | |
41 | 41 | |
42 | 42 | #--------- |
43 | 43 | # Imports |
@@ -1,274 +0,0 @@ | ||
1 | -import gc | |
2 | -import os | |
3 | -import sys | |
4 | -import signal | |
5 | -import weakref | |
6 | - | |
7 | -from cStringIO import StringIO | |
8 | - | |
9 | - | |
10 | -import unittest | |
11 | -from test.test_support import due_to_ironpython_bug | |
12 | - | |
13 | - | |
14 | -@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill") | |
15 | -@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows") | |
16 | -@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 " | |
17 | - "if threads have been used") | |
18 | -class TestBreak(unittest.TestCase): | |
19 | - | |
20 | - def setUp(self): | |
21 | - self._default_handler = signal.getsignal(signal.SIGINT) | |
22 | - | |
23 | - def tearDown(self): | |
24 | - signal.signal(signal.SIGINT, self._default_handler) | |
25 | - unittest.signals._results = weakref.WeakKeyDictionary() | |
26 | - unittest.signals._interrupt_handler = None | |
27 | - | |
28 | - | |
29 | - def testInstallHandler(self): | |
30 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
31 | - return | |
32 | - | |
33 | - default_handler = signal.getsignal(signal.SIGINT) | |
34 | - unittest.installHandler() | |
35 | - self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler) | |
36 | - | |
37 | - try: | |
38 | - pid = os.getpid() | |
39 | - os.kill(pid, signal.SIGINT) | |
40 | - except KeyboardInterrupt: | |
41 | - self.fail("KeyboardInterrupt not handled") | |
42 | - | |
43 | - self.assertTrue(unittest.signals._interrupt_handler.called) | |
44 | - | |
45 | - def testRegisterResult(self): | |
46 | - result = unittest.TestResult() | |
47 | - unittest.registerResult(result) | |
48 | - | |
49 | - for ref in unittest.signals._results: | |
50 | - if ref is result: | |
51 | - break | |
52 | - elif ref is not result: | |
53 | - self.fail("odd object in result set") | |
54 | - else: | |
55 | - self.fail("result not found") | |
56 | - | |
57 | - | |
58 | - def testInterruptCaught(self): | |
59 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
60 | - return | |
61 | - | |
62 | - default_handler = signal.getsignal(signal.SIGINT) | |
63 | - | |
64 | - result = unittest.TestResult() | |
65 | - unittest.installHandler() | |
66 | - unittest.registerResult(result) | |
67 | - | |
68 | - self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler) | |
69 | - | |
70 | - def test(result): | |
71 | - pid = os.getpid() | |
72 | - os.kill(pid, signal.SIGINT) | |
73 | - result.breakCaught = True | |
74 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
75 | - self.assertTrue(result.shouldStop) | |
76 | - | |
77 | - try: | |
78 | - test(result) | |
79 | - except KeyboardInterrupt: | |
80 | - self.fail("KeyboardInterrupt not handled") | |
81 | - self.assertTrue(result.breakCaught) | |
82 | - | |
83 | - | |
84 | - def testSecondInterrupt(self): | |
85 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
86 | - return | |
87 | - | |
88 | - result = unittest.TestResult() | |
89 | - unittest.installHandler() | |
90 | - unittest.registerResult(result) | |
91 | - | |
92 | - def test(result): | |
93 | - pid = os.getpid() | |
94 | - os.kill(pid, signal.SIGINT) | |
95 | - result.breakCaught = True | |
96 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
97 | - self.assertTrue(result.shouldStop) | |
98 | - os.kill(pid, signal.SIGINT) | |
99 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
100 | - self.fail("Second KeyboardInterrupt not raised") | |
101 | - | |
102 | - try: | |
103 | - test(result) | |
104 | - except KeyboardInterrupt: | |
105 | - pass | |
106 | - else: | |
107 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
108 | - self.fail("Second KeyboardInterrupt not raised") | |
109 | - self.assertTrue(result.breakCaught) | |
110 | - | |
111 | - | |
112 | - def testTwoResults(self): | |
113 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
114 | - return | |
115 | - | |
116 | - unittest.installHandler() | |
117 | - | |
118 | - result = unittest.TestResult() | |
119 | - unittest.registerResult(result) | |
120 | - new_handler = signal.getsignal(signal.SIGINT) | |
121 | - | |
122 | - result2 = unittest.TestResult() | |
123 | - unittest.registerResult(result2) | |
124 | - self.assertEqual(signal.getsignal(signal.SIGINT), new_handler) | |
125 | - | |
126 | - result3 = unittest.TestResult() | |
127 | - | |
128 | - def test(result): | |
129 | - pid = os.getpid() | |
130 | - os.kill(pid, signal.SIGINT) | |
131 | - | |
132 | - try: | |
133 | - test(result) | |
134 | - except KeyboardInterrupt: | |
135 | - self.fail("KeyboardInterrupt not handled") | |
136 | - | |
137 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
138 | - self.assertTrue(result.shouldStop) | |
139 | - self.assertTrue(result2.shouldStop) | |
140 | - self.assertFalse(result3.shouldStop) | |
141 | - | |
142 | - | |
143 | - def testHandlerReplacedButCalled(self): | |
144 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
145 | - # If our handler has been replaced (is no longer installed) but is | |
146 | - # called by the *new* handler, then it isn't safe to delay the | |
147 | - # SIGINT and we should immediately delegate to the default handler | |
148 | - unittest.installHandler() | |
149 | - | |
150 | - handler = signal.getsignal(signal.SIGINT) | |
151 | - def new_handler(frame, signum): | |
152 | - handler(frame, signum) | |
153 | - signal.signal(signal.SIGINT, new_handler) | |
154 | - | |
155 | - try: | |
156 | - pid = os.getpid() | |
157 | - os.kill(pid, signal.SIGINT) | |
158 | - except KeyboardInterrupt: | |
159 | - pass | |
160 | - else: | |
161 | - self.fail("replaced but delegated handler doesn't raise interrupt") | |
162 | - | |
163 | - def testRunner(self): | |
164 | - # Creating a TextTestRunner with the appropriate argument should | |
165 | - # register the TextTestResult it creates | |
166 | - runner = unittest.TextTestRunner(stream=StringIO()) | |
167 | - | |
168 | - result = runner.run(unittest.TestSuite()) | |
169 | - self.assertIn(result, unittest.signals._results) | |
170 | - | |
171 | - def testWeakReferences(self): | |
172 | - # Calling registerResult on a result should not keep it alive | |
173 | - result = unittest.TestResult() | |
174 | - unittest.registerResult(result) | |
175 | - | |
176 | - ref = weakref.ref(result) | |
177 | - del result | |
178 | - | |
179 | - # For non-reference counting implementations | |
180 | - gc.collect();gc.collect() | |
181 | - self.assertIsNone(ref()) | |
182 | - | |
183 | - | |
184 | - def testRemoveResult(self): | |
185 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
186 | - return | |
187 | - | |
188 | - result = unittest.TestResult() | |
189 | - unittest.registerResult(result) | |
190 | - | |
191 | - unittest.installHandler() | |
192 | - self.assertTrue(unittest.removeResult(result)) | |
193 | - | |
194 | - # Should this raise an error instead? | |
195 | - self.assertFalse(unittest.removeResult(unittest.TestResult())) | |
196 | - | |
197 | - try: | |
198 | - pid = os.getpid() | |
199 | - os.kill(pid, signal.SIGINT) | |
200 | - except KeyboardInterrupt: | |
201 | - pass | |
202 | - | |
203 | - self.assertFalse(result.shouldStop) | |
204 | - | |
205 | - def testMainInstallsHandler(self): | |
206 | - failfast = object() | |
207 | - test = object() | |
208 | - verbosity = object() | |
209 | - result = object() | |
210 | - default_handler = signal.getsignal(signal.SIGINT) | |
211 | - | |
212 | - class FakeRunner(object): | |
213 | - initArgs = [] | |
214 | - runArgs = [] | |
215 | - def __init__(self, *args, **kwargs): | |
216 | - self.initArgs.append((args, kwargs)) | |
217 | - def run(self, test): | |
218 | - self.runArgs.append(test) | |
219 | - return result | |
220 | - | |
221 | - class Program(unittest.TestProgram): | |
222 | - def __init__(self, catchbreak): | |
223 | - self.exit = False | |
224 | - self.verbosity = verbosity | |
225 | - self.failfast = failfast | |
226 | - self.catchbreak = catchbreak | |
227 | - self.testRunner = FakeRunner | |
228 | - self.test = test | |
229 | - self.result = None | |
230 | - | |
231 | - p = Program(False) | |
232 | - p.runTests() | |
233 | - | |
234 | - self.assertEqual(FakeRunner.initArgs, [((), {'buffer': None, | |
235 | - 'verbosity': verbosity, | |
236 | - 'failfast': failfast})]) | |
237 | - self.assertEqual(FakeRunner.runArgs, [test]) | |
238 | - self.assertEqual(p.result, result) | |
239 | - | |
240 | - self.assertEqual(signal.getsignal(signal.SIGINT), default_handler) | |
241 | - | |
242 | - FakeRunner.initArgs = [] | |
243 | - FakeRunner.runArgs = [] | |
244 | - p = Program(True) | |
245 | - p.runTests() | |
246 | - | |
247 | - self.assertEqual(FakeRunner.initArgs, [((), {'buffer': None, | |
248 | - 'verbosity': verbosity, | |
249 | - 'failfast': failfast})]) | |
250 | - self.assertEqual(FakeRunner.runArgs, [test]) | |
251 | - self.assertEqual(p.result, result) | |
252 | - | |
253 | - self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler) | |
254 | - | |
255 | - def testRemoveHandler(self): | |
256 | - default_handler = signal.getsignal(signal.SIGINT) | |
257 | - unittest.installHandler() | |
258 | - unittest.removeHandler() | |
259 | - self.assertEqual(signal.getsignal(signal.SIGINT), default_handler) | |
260 | - | |
261 | - # check that calling removeHandler multiple times has no ill-effect | |
262 | - unittest.removeHandler() | |
263 | - self.assertEqual(signal.getsignal(signal.SIGINT), default_handler) | |
264 | - | |
265 | - def testRemoveHandlerAsDecorator(self): | |
266 | - default_handler = signal.getsignal(signal.SIGINT) | |
267 | - unittest.installHandler() | |
268 | - | |
269 | - @unittest.removeHandler | |
270 | - def test(): | |
271 | - self.assertEqual(signal.getsignal(signal.SIGINT), default_handler) | |
272 | - | |
273 | - test() | |
274 | - self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler) |
@@ -1,1303 +0,0 @@ | ||
1 | -import sys | |
2 | -import types | |
3 | - | |
4 | - | |
5 | -import unittest | |
6 | -from test.test_support import due_to_ironpython_bug | |
7 | - | |
8 | - | |
9 | -class Test_TestLoader(unittest.TestCase): | |
10 | - | |
11 | - ### Tests for TestLoader.loadTestsFromTestCase | |
12 | - ################################################################ | |
13 | - | |
14 | - # "Return a suite of all tests cases contained in the TestCase-derived | |
15 | - # class testCaseClass" | |
16 | - def test_loadTestsFromTestCase(self): | |
17 | - class Foo(unittest.TestCase): | |
18 | - def test_1(self): pass | |
19 | - def test_2(self): pass | |
20 | - def foo_bar(self): pass | |
21 | - | |
22 | - tests = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) | |
23 | - | |
24 | - loader = unittest.TestLoader() | |
25 | - self.assertEqual(loader.loadTestsFromTestCase(Foo), tests) | |
26 | - | |
27 | - # "Return a suite of all tests cases contained in the TestCase-derived | |
28 | - # class testCaseClass" | |
29 | - # | |
30 | - # Make sure it does the right thing even if no tests were found | |
31 | - def test_loadTestsFromTestCase__no_matches(self): | |
32 | - class Foo(unittest.TestCase): | |
33 | - def foo_bar(self): pass | |
34 | - | |
35 | - empty_suite = unittest.TestSuite() | |
36 | - | |
37 | - loader = unittest.TestLoader() | |
38 | - self.assertEqual(loader.loadTestsFromTestCase(Foo), empty_suite) | |
39 | - | |
40 | - # "Return a suite of all tests cases contained in the TestCase-derived | |
41 | - # class testCaseClass" | |
42 | - # | |
43 | - # What happens if loadTestsFromTestCase() is given an object | |
44 | - # that isn't a subclass of TestCase? Specifically, what happens | |
45 | - # if testCaseClass is a subclass of TestSuite? | |
46 | - # | |
47 | - # This is checked for specifically in the code, so we better add a | |
48 | - # test for it. | |
49 | - def test_loadTestsFromTestCase__TestSuite_subclass(self): | |
50 | - class NotATestCase(unittest.TestSuite): | |
51 | - pass | |
52 | - | |
53 | - loader = unittest.TestLoader() | |
54 | - try: | |
55 | - loader.loadTestsFromTestCase(NotATestCase) | |
56 | - except TypeError: | |
57 | - pass | |
58 | - else: | |
59 | - self.fail('Should raise TypeError') | |
60 | - | |
61 | - # "Return a suite of all tests cases contained in the TestCase-derived | |
62 | - # class testCaseClass" | |
63 | - # | |
64 | - # Make sure loadTestsFromTestCase() picks up the default test method | |
65 | - # name (as specified by TestCase), even though the method name does | |
66 | - # not match the default TestLoader.testMethodPrefix string | |
67 | - def test_loadTestsFromTestCase__default_method_name(self): | |
68 | - class Foo(unittest.TestCase): | |
69 | - def runTest(self): | |
70 | - pass | |
71 | - | |
72 | - loader = unittest.TestLoader() | |
73 | - # This has to be false for the test to succeed | |
74 | - self.assertFalse('runTest'.startswith(loader.testMethodPrefix)) | |
75 | - | |
76 | - suite = loader.loadTestsFromTestCase(Foo) | |
77 | - self.assertIsInstance(suite, loader.suiteClass) | |
78 | - self.assertEqual(list(suite), [Foo('runTest')]) | |
79 | - | |
80 | - ################################################################ | |
81 | - ### /Tests for TestLoader.loadTestsFromTestCase | |
82 | - | |
83 | - ### Tests for TestLoader.loadTestsFromModule | |
84 | - ################################################################ | |
85 | - | |
86 | - # "This method searches `module` for classes derived from TestCase" | |
87 | - def test_loadTestsFromModule__TestCase_subclass(self): | |
88 | - m = types.ModuleType('m') | |
89 | - class MyTestCase(unittest.TestCase): | |
90 | - def test(self): | |
91 | - pass | |
92 | - m.testcase_1 = MyTestCase | |
93 | - | |
94 | - loader = unittest.TestLoader() | |
95 | - suite = loader.loadTestsFromModule(m) | |
96 | - self.assertIsInstance(suite, loader.suiteClass) | |
97 | - | |
98 | - expected = [loader.suiteClass([MyTestCase('test')])] | |
99 | - self.assertEqual(list(suite), expected) | |
100 | - | |
101 | - # "This method searches `module` for classes derived from TestCase" | |
102 | - # | |
103 | - # What happens if no tests are found (no TestCase instances)? | |
104 | - def test_loadTestsFromModule__no_TestCase_instances(self): | |
105 | - m = types.ModuleType('m') | |
106 | - | |
107 | - loader = unittest.TestLoader() | |
108 | - suite = loader.loadTestsFromModule(m) | |
109 | - self.assertIsInstance(suite, loader.suiteClass) | |
110 | - self.assertEqual(list(suite), []) | |
111 | - | |
112 | - # "This method searches `module` for classes derived from TestCase" | |
113 | - # | |
114 | - # What happens if no tests are found (TestCases instances, but no tests)? | |
115 | - def test_loadTestsFromModule__no_TestCase_tests(self): | |
116 | - m = types.ModuleType('m') | |
117 | - class MyTestCase(unittest.TestCase): | |
118 | - pass | |
119 | - m.testcase_1 = MyTestCase | |
120 | - | |
121 | - loader = unittest.TestLoader() | |
122 | - suite = loader.loadTestsFromModule(m) | |
123 | - self.assertIsInstance(suite, loader.suiteClass) | |
124 | - | |
125 | - self.assertEqual(list(suite), [loader.suiteClass()]) | |
126 | - | |
127 | - # "This method searches `module` for classes derived from TestCase"s | |
128 | - # | |
129 | - # What happens if loadTestsFromModule() is given something other | |
130 | - # than a module? | |
131 | - # | |
132 | - # XXX Currently, it succeeds anyway. This flexibility | |
133 | - # should either be documented or loadTestsFromModule() should | |
134 | - # raise a TypeError | |
135 | - # | |
136 | - # XXX Certain people are using this behaviour. We'll add a test for it | |
137 | - def test_loadTestsFromModule__not_a_module(self): | |
138 | - class MyTestCase(unittest.TestCase): | |
139 | - def test(self): | |
140 | - pass | |
141 | - | |
142 | - class NotAModule(object): | |
143 | - test_2 = MyTestCase | |
144 | - | |
145 | - loader = unittest.TestLoader() | |
146 | - suite = loader.loadTestsFromModule(NotAModule) | |
147 | - | |
148 | - reference = [unittest.TestSuite([MyTestCase('test')])] | |
149 | - self.assertEqual(list(suite), reference) | |
150 | - | |
151 | - | |
152 | - # Check that loadTestsFromModule honors (or not) a module | |
153 | - # with a load_tests function. | |
154 | - def test_loadTestsFromModule__load_tests(self): | |
155 | - m = types.ModuleType('m') | |
156 | - class MyTestCase(unittest.TestCase): | |
157 | - def test(self): | |
158 | - pass | |
159 | - m.testcase_1 = MyTestCase | |
160 | - | |
161 | - load_tests_args = [] | |
162 | - def load_tests(loader, tests, pattern): | |
163 | - self.assertIsInstance(tests, unittest.TestSuite) | |
164 | - load_tests_args.extend((loader, tests, pattern)) | |
165 | - return tests | |
166 | - m.load_tests = load_tests | |
167 | - | |
168 | - loader = unittest.TestLoader() | |
169 | - suite = loader.loadTestsFromModule(m) | |
170 | - self.assertIsInstance(suite, unittest.TestSuite) | |
171 | - self.assertEquals(load_tests_args, [loader, suite, None]) | |
172 | - | |
173 | - load_tests_args = [] | |
174 | - suite = loader.loadTestsFromModule(m, use_load_tests=False) | |
175 | - self.assertEquals(load_tests_args, []) | |
176 | - | |
177 | - def test_loadTestsFromModule__faulty_load_tests(self): | |
178 | - m = types.ModuleType('m') | |
179 | - | |
180 | - def load_tests(loader, tests, pattern): | |
181 | - raise TypeError('some failure') | |
182 | - m.load_tests = load_tests | |
183 | - | |
184 | - loader = unittest.TestLoader() | |
185 | - suite = loader.loadTestsFromModule(m) | |
186 | - self.assertIsInstance(suite, unittest.TestSuite) | |
187 | - self.assertEqual(suite.countTestCases(), 1) | |
188 | - test = list(suite)[0] | |
189 | - | |
190 | - self.assertRaisesRegexp(TypeError, "some failure", test.m) | |
191 | - | |
192 | - ################################################################ | |
193 | - ### /Tests for TestLoader.loadTestsFromModule() | |
194 | - | |
195 | - ### Tests for TestLoader.loadTestsFromName() | |
196 | - ################################################################ | |
197 | - | |
198 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
199 | - # a module, a test case class, a TestSuite instance, a test method | |
200 | - # within a test case class, or a callable object which returns a | |
201 | - # TestCase or TestSuite instance." | |
202 | - # | |
203 | - # Is ValueError raised in response to an empty name? | |
204 | - def test_loadTestsFromName__empty_name(self): | |
205 | - loader = unittest.TestLoader() | |
206 | - | |
207 | - try: | |
208 | - loader.loadTestsFromName('') | |
209 | - except ValueError, e: | |
210 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
211 | - self.assertEqual(str(e), "String cannot have zero length.") | |
212 | - else: | |
213 | - self.assertEqual(str(e), "Empty module name") | |
214 | - else: | |
215 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
216 | - self.fail("TestLoader.loadTestsFromName failed to raise ValueError") | |
217 | - | |
218 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
219 | - # a module, a test case class, a TestSuite instance, a test method | |
220 | - # within a test case class, or a callable object which returns a | |
221 | - # TestCase or TestSuite instance." | |
222 | - # | |
223 | - # What happens when the name contains invalid characters? | |
224 | - def test_loadTestsFromName__malformed_name(self): | |
225 | - loader = unittest.TestLoader() | |
226 | - | |
227 | - # XXX Should this raise ValueError or ImportError? | |
228 | - try: | |
229 | - loader.loadTestsFromName('abc () //') | |
230 | - except ValueError: | |
231 | - pass | |
232 | - except ImportError: | |
233 | - pass | |
234 | - else: | |
235 | - self.fail("TestLoader.loadTestsFromName failed to raise ValueError") | |
236 | - | |
237 | - # "The specifier name is a ``dotted name'' that may resolve ... to a | |
238 | - # module" | |
239 | - # | |
240 | - # What happens when a module by that name can't be found? | |
241 | - def test_loadTestsFromName__unknown_module_name(self): | |
242 | - loader = unittest.TestLoader() | |
243 | - | |
244 | - try: | |
245 | - loader.loadTestsFromName('sdasfasfasdf') | |
246 | - except ImportError, e: | |
247 | - self.assertEqual(str(e), "No module named sdasfasfasdf") | |
248 | - else: | |
249 | - self.fail("TestLoader.loadTestsFromName failed to raise ImportError") | |
250 | - | |
251 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
252 | - # a module, a test case class, a TestSuite instance, a test method | |
253 | - # within a test case class, or a callable object which returns a | |
254 | - # TestCase or TestSuite instance." | |
255 | - # | |
256 | - # What happens when the module is found, but the attribute can't? | |
257 | - def test_loadTestsFromName__unknown_attr_name(self): | |
258 | - loader = unittest.TestLoader() | |
259 | - | |
260 | - try: | |
261 | - loader.loadTestsFromName('unittest.sdasfasfasdf') | |
262 | - except AttributeError, e: | |
263 | - self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") | |
264 | - else: | |
265 | - self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") | |
266 | - | |
267 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
268 | - # a module, a test case class, a TestSuite instance, a test method | |
269 | - # within a test case class, or a callable object which returns a | |
270 | - # TestCase or TestSuite instance." | |
271 | - # | |
272 | - # What happens when we provide the module, but the attribute can't be | |
273 | - # found? | |
274 | - def test_loadTestsFromName__relative_unknown_name(self): | |
275 | - loader = unittest.TestLoader() | |
276 | - | |
277 | - try: | |
278 | - loader.loadTestsFromName('sdasfasfasdf', unittest) | |
279 | - except AttributeError, e: | |
280 | - self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") | |
281 | - else: | |
282 | - self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") | |
283 | - | |
284 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
285 | - # a module, a test case class, a TestSuite instance, a test method | |
286 | - # within a test case class, or a callable object which returns a | |
287 | - # TestCase or TestSuite instance." | |
288 | - # ... | |
289 | - # "The method optionally resolves name relative to the given module" | |
290 | - # | |
291 | - # Does loadTestsFromName raise ValueError when passed an empty | |
292 | - # name relative to a provided module? | |
293 | - # | |
294 | - # XXX Should probably raise a ValueError instead of an AttributeError | |
295 | - def test_loadTestsFromName__relative_empty_name(self): | |
296 | - loader = unittest.TestLoader() | |
297 | - | |
298 | - try: | |
299 | - loader.loadTestsFromName('', unittest) | |
300 | - except AttributeError: | |
301 | - pass | |
302 | - else: | |
303 | - self.fail("Failed to raise AttributeError") | |
304 | - | |
305 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
306 | - # a module, a test case class, a TestSuite instance, a test method | |
307 | - # within a test case class, or a callable object which returns a | |
308 | - # TestCase or TestSuite instance." | |
309 | - # ... | |
310 | - # "The method optionally resolves name relative to the given module" | |
311 | - # | |
312 | - # What happens when an impossible name is given, relative to the provided | |
313 | - # `module`? | |
314 | - def test_loadTestsFromName__relative_malformed_name(self): | |
315 | - loader = unittest.TestLoader() | |
316 | - | |
317 | - # XXX Should this raise AttributeError or ValueError? | |
318 | - try: | |
319 | - loader.loadTestsFromName('abc () //', unittest) | |
320 | - except ValueError: | |
321 | - pass | |
322 | - except AttributeError: | |
323 | - pass | |
324 | - else: | |
325 | - self.fail("TestLoader.loadTestsFromName failed to raise ValueError") | |
326 | - | |
327 | - # "The method optionally resolves name relative to the given module" | |
328 | - # | |
329 | - # Does loadTestsFromName raise TypeError when the `module` argument | |
330 | - # isn't a module object? | |
331 | - # | |
332 | - # XXX Accepts the not-a-module object, ignorning the object's type | |
333 | - # This should raise an exception or the method name should be changed | |
334 | - # | |
335 | - # XXX Some people are relying on this, so keep it for now | |
336 | - def test_loadTestsFromName__relative_not_a_module(self): | |
337 | - class MyTestCase(unittest.TestCase): | |
338 | - def test(self): | |
339 | - pass | |
340 | - | |
341 | - class NotAModule(object): | |
342 | - test_2 = MyTestCase | |
343 | - | |
344 | - loader = unittest.TestLoader() | |
345 | - suite = loader.loadTestsFromName('test_2', NotAModule) | |
346 | - | |
347 | - reference = [MyTestCase('test')] | |
348 | - self.assertEqual(list(suite), reference) | |
349 | - | |
350 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
351 | - # a module, a test case class, a TestSuite instance, a test method | |
352 | - # within a test case class, or a callable object which returns a | |
353 | - # TestCase or TestSuite instance." | |
354 | - # | |
355 | - # Does it raise an exception if the name resolves to an invalid | |
356 | - # object? | |
357 | - def test_loadTestsFromName__relative_bad_object(self): | |
358 | - m = types.ModuleType('m') | |
359 | - m.testcase_1 = object() | |
360 | - | |
361 | - loader = unittest.TestLoader() | |
362 | - try: | |
363 | - loader.loadTestsFromName('testcase_1', m) | |
364 | - except TypeError: | |
365 | - pass | |
366 | - else: | |
367 | - self.fail("Should have raised TypeError") | |
368 | - | |
369 | - # "The specifier name is a ``dotted name'' that may | |
370 | - # resolve either to ... a test case class" | |
371 | - def test_loadTestsFromName__relative_TestCase_subclass(self): | |
372 | - m = types.ModuleType('m') | |
373 | - class MyTestCase(unittest.TestCase): | |
374 | - def test(self): | |
375 | - pass | |
376 | - m.testcase_1 = MyTestCase | |
377 | - | |
378 | - loader = unittest.TestLoader() | |
379 | - suite = loader.loadTestsFromName('testcase_1', m) | |
380 | - self.assertIsInstance(suite, loader.suiteClass) | |
381 | - self.assertEqual(list(suite), [MyTestCase('test')]) | |
382 | - | |
383 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
384 | - # a module, a test case class, a TestSuite instance, a test method | |
385 | - # within a test case class, or a callable object which returns a | |
386 | - # TestCase or TestSuite instance." | |
387 | - def test_loadTestsFromName__relative_TestSuite(self): | |
388 | - m = types.ModuleType('m') | |
389 | - class MyTestCase(unittest.TestCase): | |
390 | - def test(self): | |
391 | - pass | |
392 | - m.testsuite = unittest.TestSuite([MyTestCase('test')]) | |
393 | - | |
394 | - loader = unittest.TestLoader() | |
395 | - suite = loader.loadTestsFromName('testsuite', m) | |
396 | - self.assertIsInstance(suite, loader.suiteClass) | |
397 | - | |
398 | - self.assertEqual(list(suite), [MyTestCase('test')]) | |
399 | - | |
400 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
401 | - # ... a test method within a test case class" | |
402 | - def test_loadTestsFromName__relative_testmethod(self): | |
403 | - m = types.ModuleType('m') | |
404 | - class MyTestCase(unittest.TestCase): | |
405 | - def test(self): | |
406 | - pass | |
407 | - m.testcase_1 = MyTestCase | |
408 | - | |
409 | - loader = unittest.TestLoader() | |
410 | - suite = loader.loadTestsFromName('testcase_1.test', m) | |
411 | - self.assertIsInstance(suite, loader.suiteClass) | |
412 | - | |
413 | - self.assertEqual(list(suite), [MyTestCase('test')]) | |
414 | - | |
415 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
416 | - # a module, a test case class, a TestSuite instance, a test method | |
417 | - # within a test case class, or a callable object which returns a | |
418 | - # TestCase or TestSuite instance." | |
419 | - # | |
420 | - # Does loadTestsFromName() raise the proper exception when trying to | |
421 | - # resolve "a test method within a test case class" that doesn't exist | |
422 | - # for the given name (relative to a provided module)? | |
423 | - def test_loadTestsFromName__relative_invalid_testmethod(self): | |
424 | - m = types.ModuleType('m') | |
425 | - class MyTestCase(unittest.TestCase): | |
426 | - def test(self): | |
427 | - pass | |
428 | - m.testcase_1 = MyTestCase | |
429 | - | |
430 | - loader = unittest.TestLoader() | |
431 | - try: | |
432 | - loader.loadTestsFromName('testcase_1.testfoo', m) | |
433 | - except AttributeError, e: | |
434 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
435 | - self.assertEqual(str(e), "'type' object has no attribute 'testfoo'") | |
436 | - else: | |
437 | - self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'") | |
438 | - else: | |
439 | - self.fail("Failed to raise AttributeError") | |
440 | - | |
441 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
442 | - # ... a callable object which returns a ... TestSuite instance" | |
443 | - def test_loadTestsFromName__callable__TestSuite(self): | |
444 | - m = types.ModuleType('m') | |
445 | - testcase_1 = unittest.FunctionTestCase(lambda: None) | |
446 | - testcase_2 = unittest.FunctionTestCase(lambda: None) | |
447 | - def return_TestSuite(): | |
448 | - return unittest.TestSuite([testcase_1, testcase_2]) | |
449 | - m.return_TestSuite = return_TestSuite | |
450 | - | |
451 | - loader = unittest.TestLoader() | |
452 | - suite = loader.loadTestsFromName('return_TestSuite', m) | |
453 | - self.assertIsInstance(suite, loader.suiteClass) | |
454 | - self.assertEqual(list(suite), [testcase_1, testcase_2]) | |
455 | - | |
456 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
457 | - # ... a callable object which returns a TestCase ... instance" | |
458 | - def test_loadTestsFromName__callable__TestCase_instance(self): | |
459 | - m = types.ModuleType('m') | |
460 | - testcase_1 = unittest.FunctionTestCase(lambda: None) | |
461 | - def return_TestCase(): | |
462 | - return testcase_1 | |
463 | - m.return_TestCase = return_TestCase | |
464 | - | |
465 | - loader = unittest.TestLoader() | |
466 | - suite = loader.loadTestsFromName('return_TestCase', m) | |
467 | - self.assertIsInstance(suite, loader.suiteClass) | |
468 | - self.assertEqual(list(suite), [testcase_1]) | |
469 | - | |
470 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
471 | - # ... a callable object which returns a TestCase ... instance" | |
472 | - #***************************************************************** | |
473 | - #Override the suiteClass attribute to ensure that the suiteClass | |
474 | - #attribute is used | |
475 | - def test_loadTestsFromName__callable__TestCase_instance_ProperSuiteClass(self): | |
476 | - class SubTestSuite(unittest.TestSuite): | |
477 | - pass | |
478 | - m = types.ModuleType('m') | |
479 | - testcase_1 = unittest.FunctionTestCase(lambda: None) | |
480 | - def return_TestCase(): | |
481 | - return testcase_1 | |
482 | - m.return_TestCase = return_TestCase | |
483 | - | |
484 | - loader = unittest.TestLoader() | |
485 | - loader.suiteClass = SubTestSuite | |
486 | - suite = loader.loadTestsFromName('return_TestCase', m) | |
487 | - self.assertIsInstance(suite, loader.suiteClass) | |
488 | - self.assertEqual(list(suite), [testcase_1]) | |
489 | - | |
490 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
491 | - # ... a test method within a test case class" | |
492 | - #***************************************************************** | |
493 | - #Override the suiteClass attribute to ensure that the suiteClass | |
494 | - #attribute is used | |
495 | - def test_loadTestsFromName__relative_testmethod_ProperSuiteClass(self): | |
496 | - class SubTestSuite(unittest.TestSuite): | |
497 | - pass | |
498 | - m = types.ModuleType('m') | |
499 | - class MyTestCase(unittest.TestCase): | |
500 | - def test(self): | |
501 | - pass | |
502 | - m.testcase_1 = MyTestCase | |
503 | - | |
504 | - loader = unittest.TestLoader() | |
505 | - loader.suiteClass=SubTestSuite | |
506 | - suite = loader.loadTestsFromName('testcase_1.test', m) | |
507 | - self.assertIsInstance(suite, loader.suiteClass) | |
508 | - | |
509 | - self.assertEqual(list(suite), [MyTestCase('test')]) | |
510 | - | |
511 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
512 | - # ... a callable object which returns a TestCase or TestSuite instance" | |
513 | - # | |
514 | - # What happens if the callable returns something else? | |
515 | - def test_loadTestsFromName__callable__wrong_type(self): | |
516 | - m = types.ModuleType('m') | |
517 | - def return_wrong(): | |
518 | - return 6 | |
519 | - m.return_wrong = return_wrong | |
520 | - | |
521 | - loader = unittest.TestLoader() | |
522 | - try: | |
523 | - loader.loadTestsFromName('return_wrong', m) | |
524 | - except TypeError: | |
525 | - pass | |
526 | - else: | |
527 | - self.fail("TestLoader.loadTestsFromName failed to raise TypeError") | |
528 | - | |
529 | - # "The specifier can refer to modules and packages which have not been | |
530 | - # imported; they will be imported as a side-effect" | |
531 | - def test_loadTestsFromName__module_not_loaded(self): | |
532 | - # We're going to try to load this module as a side-effect, so it | |
533 | - # better not be loaded before we try. | |
534 | - # | |
535 | - module_name = 'unittest.test.dummy' | |
536 | - sys.modules.pop(module_name, None) | |
537 | - | |
538 | - loader = unittest.TestLoader() | |
539 | - try: | |
540 | - suite = loader.loadTestsFromName(module_name) | |
541 | - | |
542 | - self.assertIsInstance(suite, loader.suiteClass) | |
543 | - self.assertEqual(list(suite), []) | |
544 | - | |
545 | - # module should now be loaded, thanks to loadTestsFromName() | |
546 | - self.assertIn(module_name, sys.modules) | |
547 | - finally: | |
548 | - if module_name in sys.modules: | |
549 | - del sys.modules[module_name] | |
550 | - | |
551 | - ################################################################ | |
552 | - ### Tests for TestLoader.loadTestsFromName() | |
553 | - | |
554 | - ### Tests for TestLoader.loadTestsFromNames() | |
555 | - ################################################################ | |
556 | - | |
557 | - # "Similar to loadTestsFromName(), but takes a sequence of names rather | |
558 | - # than a single name." | |
559 | - # | |
560 | - # What happens if that sequence of names is empty? | |
561 | - def test_loadTestsFromNames__empty_name_list(self): | |
562 | - loader = unittest.TestLoader() | |
563 | - | |
564 | - suite = loader.loadTestsFromNames([]) | |
565 | - self.assertIsInstance(suite, loader.suiteClass) | |
566 | - self.assertEqual(list(suite), []) | |
567 | - | |
568 | - # "Similar to loadTestsFromName(), but takes a sequence of names rather | |
569 | - # than a single name." | |
570 | - # ... | |
571 | - # "The method optionally resolves name relative to the given module" | |
572 | - # | |
573 | - # What happens if that sequence of names is empty? | |
574 | - # | |
575 | - # XXX Should this raise a ValueError or just return an empty TestSuite? | |
576 | - def test_loadTestsFromNames__relative_empty_name_list(self): | |
577 | - loader = unittest.TestLoader() | |
578 | - | |
579 | - suite = loader.loadTestsFromNames([], unittest) | |
580 | - self.assertIsInstance(suite, loader.suiteClass) | |
581 | - self.assertEqual(list(suite), []) | |
582 | - | |
583 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
584 | - # a module, a test case class, a TestSuite instance, a test method | |
585 | - # within a test case class, or a callable object which returns a | |
586 | - # TestCase or TestSuite instance." | |
587 | - # | |
588 | - # Is ValueError raised in response to an empty name? | |
589 | - def test_loadTestsFromNames__empty_name(self): | |
590 | - loader = unittest.TestLoader() | |
591 | - | |
592 | - try: | |
593 | - loader.loadTestsFromNames(['']) | |
594 | - except ValueError, e: | |
595 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
596 | - self.assertEqual(str(e), "String cannot have zero length.") | |
597 | - else: | |
598 | - self.assertEqual(str(e), "Empty module name") | |
599 | - else: | |
600 | - # only seems to be a problem on win7 | |
601 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
602 | - self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") | |
603 | - | |
604 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
605 | - # a module, a test case class, a TestSuite instance, a test method | |
606 | - # within a test case class, or a callable object which returns a | |
607 | - # TestCase or TestSuite instance." | |
608 | - # | |
609 | - # What happens when presented with an impossible module name? | |
610 | - def test_loadTestsFromNames__malformed_name(self): | |
611 | - loader = unittest.TestLoader() | |
612 | - | |
613 | - # XXX Should this raise ValueError or ImportError? | |
614 | - try: | |
615 | - loader.loadTestsFromNames(['abc () //']) | |
616 | - except ValueError: | |
617 | - pass | |
618 | - except ImportError: | |
619 | - pass | |
620 | - else: | |
621 | - self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") | |
622 | - | |
623 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
624 | - # a module, a test case class, a TestSuite instance, a test method | |
625 | - # within a test case class, or a callable object which returns a | |
626 | - # TestCase or TestSuite instance." | |
627 | - # | |
628 | - # What happens when no module can be found for the given name? | |
629 | - def test_loadTestsFromNames__unknown_module_name(self): | |
630 | - loader = unittest.TestLoader() | |
631 | - | |
632 | - try: | |
633 | - loader.loadTestsFromNames(['sdasfasfasdf']) | |
634 | - except ImportError, e: | |
635 | - self.assertEqual(str(e), "No module named sdasfasfasdf") | |
636 | - else: | |
637 | - self.fail("TestLoader.loadTestsFromNames failed to raise ImportError") | |
638 | - | |
639 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
640 | - # a module, a test case class, a TestSuite instance, a test method | |
641 | - # within a test case class, or a callable object which returns a | |
642 | - # TestCase or TestSuite instance." | |
643 | - # | |
644 | - # What happens when the module can be found, but not the attribute? | |
645 | - def test_loadTestsFromNames__unknown_attr_name(self): | |
646 | - loader = unittest.TestLoader() | |
647 | - | |
648 | - try: | |
649 | - loader.loadTestsFromNames(['unittest.sdasfasfasdf', 'unittest']) | |
650 | - except AttributeError, e: | |
651 | - self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") | |
652 | - else: | |
653 | - self.fail("TestLoader.loadTestsFromNames failed to raise AttributeError") | |
654 | - | |
655 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
656 | - # a module, a test case class, a TestSuite instance, a test method | |
657 | - # within a test case class, or a callable object which returns a | |
658 | - # TestCase or TestSuite instance." | |
659 | - # ... | |
660 | - # "The method optionally resolves name relative to the given module" | |
661 | - # | |
662 | - # What happens when given an unknown attribute on a specified `module` | |
663 | - # argument? | |
664 | - def test_loadTestsFromNames__unknown_name_relative_1(self): | |
665 | - loader = unittest.TestLoader() | |
666 | - | |
667 | - try: | |
668 | - loader.loadTestsFromNames(['sdasfasfasdf'], unittest) | |
669 | - except AttributeError, e: | |
670 | - self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") | |
671 | - else: | |
672 | - self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") | |
673 | - | |
674 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
675 | - # a module, a test case class, a TestSuite instance, a test method | |
676 | - # within a test case class, or a callable object which returns a | |
677 | - # TestCase or TestSuite instance." | |
678 | - # ... | |
679 | - # "The method optionally resolves name relative to the given module" | |
680 | - # | |
681 | - # Do unknown attributes (relative to a provided module) still raise an | |
682 | - # exception even in the presence of valid attribute names? | |
683 | - def test_loadTestsFromNames__unknown_name_relative_2(self): | |
684 | - loader = unittest.TestLoader() | |
685 | - | |
686 | - try: | |
687 | - loader.loadTestsFromNames(['TestCase', 'sdasfasfasdf'], unittest) | |
688 | - except AttributeError, e: | |
689 | - self.assertEqual(str(e), "'module' object has no attribute 'sdasfasfasdf'") | |
690 | - else: | |
691 | - self.fail("TestLoader.loadTestsFromName failed to raise AttributeError") | |
692 | - | |
693 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
694 | - # a module, a test case class, a TestSuite instance, a test method | |
695 | - # within a test case class, or a callable object which returns a | |
696 | - # TestCase or TestSuite instance." | |
697 | - # ... | |
698 | - # "The method optionally resolves name relative to the given module" | |
699 | - # | |
700 | - # What happens when faced with the empty string? | |
701 | - # | |
702 | - # XXX This currently raises AttributeError, though ValueError is probably | |
703 | - # more appropriate | |
704 | - def test_loadTestsFromNames__relative_empty_name(self): | |
705 | - loader = unittest.TestLoader() | |
706 | - | |
707 | - try: | |
708 | - loader.loadTestsFromNames([''], unittest) | |
709 | - except AttributeError: | |
710 | - pass | |
711 | - else: | |
712 | - self.fail("Failed to raise ValueError") | |
713 | - | |
714 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
715 | - # a module, a test case class, a TestSuite instance, a test method | |
716 | - # within a test case class, or a callable object which returns a | |
717 | - # TestCase or TestSuite instance." | |
718 | - # ... | |
719 | - # "The method optionally resolves name relative to the given module" | |
720 | - # | |
721 | - # What happens when presented with an impossible attribute name? | |
722 | - def test_loadTestsFromNames__relative_malformed_name(self): | |
723 | - loader = unittest.TestLoader() | |
724 | - | |
725 | - # XXX Should this raise AttributeError or ValueError? | |
726 | - try: | |
727 | - loader.loadTestsFromNames(['abc () //'], unittest) | |
728 | - except AttributeError: | |
729 | - pass | |
730 | - except ValueError: | |
731 | - pass | |
732 | - else: | |
733 | - self.fail("TestLoader.loadTestsFromNames failed to raise ValueError") | |
734 | - | |
735 | - # "The method optionally resolves name relative to the given module" | |
736 | - # | |
737 | - # Does loadTestsFromNames() make sure the provided `module` is in fact | |
738 | - # a module? | |
739 | - # | |
740 | - # XXX This validation is currently not done. This flexibility should | |
741 | - # either be documented or a TypeError should be raised. | |
742 | - def test_loadTestsFromNames__relative_not_a_module(self): | |
743 | - class MyTestCase(unittest.TestCase): | |
744 | - def test(self): | |
745 | - pass | |
746 | - | |
747 | - class NotAModule(object): | |
748 | - test_2 = MyTestCase | |
749 | - | |
750 | - loader = unittest.TestLoader() | |
751 | - suite = loader.loadTestsFromNames(['test_2'], NotAModule) | |
752 | - | |
753 | - reference = [unittest.TestSuite([MyTestCase('test')])] | |
754 | - self.assertEqual(list(suite), reference) | |
755 | - | |
756 | - # "The specifier name is a ``dotted name'' that may resolve either to | |
757 | - # a module, a test case class, a TestSuite instance, a test method | |
758 | - # within a test case class, or a callable object which returns a | |
759 | - # TestCase or TestSuite instance." | |
760 | - # | |
761 | - # Does it raise an exception if the name resolves to an invalid | |
762 | - # object? | |
763 | - def test_loadTestsFromNames__relative_bad_object(self): | |
764 | - m = types.ModuleType('m') | |
765 | - m.testcase_1 = object() | |
766 | - | |
767 | - loader = unittest.TestLoader() | |
768 | - try: | |
769 | - loader.loadTestsFromNames(['testcase_1'], m) | |
770 | - except TypeError: | |
771 | - pass | |
772 | - else: | |
773 | - self.fail("Should have raised TypeError") | |
774 | - | |
775 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
776 | - # ... a test case class" | |
777 | - def test_loadTestsFromNames__relative_TestCase_subclass(self): | |
778 | - m = types.ModuleType('m') | |
779 | - class MyTestCase(unittest.TestCase): | |
780 | - def test(self): | |
781 | - pass | |
782 | - m.testcase_1 = MyTestCase | |
783 | - | |
784 | - loader = unittest.TestLoader() | |
785 | - suite = loader.loadTestsFromNames(['testcase_1'], m) | |
786 | - self.assertIsInstance(suite, loader.suiteClass) | |
787 | - | |
788 | - expected = loader.suiteClass([MyTestCase('test')]) | |
789 | - self.assertEqual(list(suite), [expected]) | |
790 | - | |
791 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
792 | - # ... a TestSuite instance" | |
793 | - def test_loadTestsFromNames__relative_TestSuite(self): | |
794 | - m = types.ModuleType('m') | |
795 | - class MyTestCase(unittest.TestCase): | |
796 | - def test(self): | |
797 | - pass | |
798 | - m.testsuite = unittest.TestSuite([MyTestCase('test')]) | |
799 | - | |
800 | - loader = unittest.TestLoader() | |
801 | - suite = loader.loadTestsFromNames(['testsuite'], m) | |
802 | - self.assertIsInstance(suite, loader.suiteClass) | |
803 | - | |
804 | - self.assertEqual(list(suite), [m.testsuite]) | |
805 | - | |
806 | - # "The specifier name is a ``dotted name'' that may resolve ... to ... a | |
807 | - # test method within a test case class" | |
808 | - def test_loadTestsFromNames__relative_testmethod(self): | |
809 | - m = types.ModuleType('m') | |
810 | - class MyTestCase(unittest.TestCase): | |
811 | - def test(self): | |
812 | - pass | |
813 | - m.testcase_1 = MyTestCase | |
814 | - | |
815 | - loader = unittest.TestLoader() | |
816 | - suite = loader.loadTestsFromNames(['testcase_1.test'], m) | |
817 | - self.assertIsInstance(suite, loader.suiteClass) | |
818 | - | |
819 | - ref_suite = unittest.TestSuite([MyTestCase('test')]) | |
820 | - self.assertEqual(list(suite), [ref_suite]) | |
821 | - | |
822 | - # "The specifier name is a ``dotted name'' that may resolve ... to ... a | |
823 | - # test method within a test case class" | |
824 | - # | |
825 | - # Does the method gracefully handle names that initially look like they | |
826 | - # resolve to "a test method within a test case class" but don't? | |
827 | - def test_loadTestsFromNames__relative_invalid_testmethod(self): | |
828 | - m = types.ModuleType('m') | |
829 | - class MyTestCase(unittest.TestCase): | |
830 | - def test(self): | |
831 | - pass | |
832 | - m.testcase_1 = MyTestCase | |
833 | - | |
834 | - loader = unittest.TestLoader() | |
835 | - try: | |
836 | - loader.loadTestsFromNames(['testcase_1.testfoo'], m) | |
837 | - except AttributeError, e: | |
838 | - if due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/21116"): | |
839 | - self.assertEqual(str(e), "'type' object has no attribute 'testfoo'") | |
840 | - else: | |
841 | - self.assertEqual(str(e), "type object 'MyTestCase' has no attribute 'testfoo'") | |
842 | - else: | |
843 | - self.fail("Failed to raise AttributeError") | |
844 | - | |
845 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
846 | - # ... a callable object which returns a ... TestSuite instance" | |
847 | - def test_loadTestsFromNames__callable__TestSuite(self): | |
848 | - m = types.ModuleType('m') | |
849 | - testcase_1 = unittest.FunctionTestCase(lambda: None) | |
850 | - testcase_2 = unittest.FunctionTestCase(lambda: None) | |
851 | - def return_TestSuite(): | |
852 | - return unittest.TestSuite([testcase_1, testcase_2]) | |
853 | - m.return_TestSuite = return_TestSuite | |
854 | - | |
855 | - loader = unittest.TestLoader() | |
856 | - suite = loader.loadTestsFromNames(['return_TestSuite'], m) | |
857 | - self.assertIsInstance(suite, loader.suiteClass) | |
858 | - | |
859 | - expected = unittest.TestSuite([testcase_1, testcase_2]) | |
860 | - self.assertEqual(list(suite), [expected]) | |
861 | - | |
862 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
863 | - # ... a callable object which returns a TestCase ... instance" | |
864 | - def test_loadTestsFromNames__callable__TestCase_instance(self): | |
865 | - m = types.ModuleType('m') | |
866 | - testcase_1 = unittest.FunctionTestCase(lambda: None) | |
867 | - def return_TestCase(): | |
868 | - return testcase_1 | |
869 | - m.return_TestCase = return_TestCase | |
870 | - | |
871 | - loader = unittest.TestLoader() | |
872 | - suite = loader.loadTestsFromNames(['return_TestCase'], m) | |
873 | - self.assertIsInstance(suite, loader.suiteClass) | |
874 | - | |
875 | - ref_suite = unittest.TestSuite([testcase_1]) | |
876 | - self.assertEqual(list(suite), [ref_suite]) | |
877 | - | |
878 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
879 | - # ... a callable object which returns a TestCase or TestSuite instance" | |
880 | - # | |
881 | - # Are staticmethods handled correctly? | |
882 | - def test_loadTestsFromNames__callable__call_staticmethod(self): | |
883 | - m = types.ModuleType('m') | |
884 | - class Test1(unittest.TestCase): | |
885 | - def test(self): | |
886 | - pass | |
887 | - | |
888 | - testcase_1 = Test1('test') | |
889 | - class Foo(unittest.TestCase): | |
890 | - @staticmethod | |
891 | - def foo(): | |
892 | - return testcase_1 | |
893 | - m.Foo = Foo | |
894 | - | |
895 | - loader = unittest.TestLoader() | |
896 | - suite = loader.loadTestsFromNames(['Foo.foo'], m) | |
897 | - self.assertIsInstance(suite, loader.suiteClass) | |
898 | - | |
899 | - ref_suite = unittest.TestSuite([testcase_1]) | |
900 | - self.assertEqual(list(suite), [ref_suite]) | |
901 | - | |
902 | - # "The specifier name is a ``dotted name'' that may resolve ... to | |
903 | - # ... a callable object which returns a TestCase or TestSuite instance" | |
904 | - # | |
905 | - # What happens when the callable returns something else? | |
906 | - def test_loadTestsFromNames__callable__wrong_type(self): | |
907 | - m = types.ModuleType('m') | |
908 | - def return_wrong(): | |
909 | - return 6 | |
910 | - m.return_wrong = return_wrong | |
911 | - | |
912 | - loader = unittest.TestLoader() | |
913 | - try: | |
914 | - loader.loadTestsFromNames(['return_wrong'], m) | |
915 | - except TypeError: | |
916 | - pass | |
917 | - else: | |
918 | - self.fail("TestLoader.loadTestsFromNames failed to raise TypeError") | |
919 | - | |
920 | - # "The specifier can refer to modules and packages which have not been | |
921 | - # imported; they will be imported as a side-effect" | |
922 | - def test_loadTestsFromNames__module_not_loaded(self): | |
923 | - # We're going to try to load this module as a side-effect, so it | |
924 | - # better not be loaded before we try. | |
925 | - # | |
926 | - module_name = 'unittest.test.dummy' | |
927 | - sys.modules.pop(module_name, None) | |
928 | - | |
929 | - loader = unittest.TestLoader() | |
930 | - try: | |
931 | - suite = loader.loadTestsFromNames([module_name]) | |
932 | - | |
933 | - self.assertIsInstance(suite, loader.suiteClass) | |
934 | - self.assertEqual(list(suite), [unittest.TestSuite()]) | |
935 | - | |
936 | - # module should now be loaded, thanks to loadTestsFromName() | |
937 | - if not due_to_ironpython_bug("http://ironpython.codeplex.com/workitem/28171"): | |
938 | - self.assertIn(module_name, sys.modules) | |
939 | - finally: | |
940 | - if module_name in sys.modules: | |
941 | - del sys.modules[module_name] | |
942 | - | |
943 | - ################################################################ | |
944 | - ### /Tests for TestLoader.loadTestsFromNames() | |
945 | - | |
946 | - ### Tests for TestLoader.getTestCaseNames() | |
947 | - ################################################################ | |
948 | - | |
949 | - # "Return a sorted sequence of method names found within testCaseClass" | |
950 | - # | |
951 | - # Test.foobar is defined to make sure getTestCaseNames() respects | |
952 | - # loader.testMethodPrefix | |
953 | - def test_getTestCaseNames(self): | |
954 | - class Test(unittest.TestCase): | |
955 | - def test_1(self): pass | |
956 | - def test_2(self): pass | |
957 | - def foobar(self): pass | |
958 | - | |
959 | - loader = unittest.TestLoader() | |
960 | - | |
961 | - self.assertEqual(loader.getTestCaseNames(Test), ['test_1', 'test_2']) | |
962 | - | |
963 | - # "Return a sorted sequence of method names found within testCaseClass" | |
964 | - # | |
965 | - # Does getTestCaseNames() behave appropriately if no tests are found? | |
966 | - def test_getTestCaseNames__no_tests(self): | |
967 | - class Test(unittest.TestCase): | |
968 | - def foobar(self): pass | |
969 | - | |
970 | - loader = unittest.TestLoader() | |
971 | - | |
972 | - self.assertEqual(loader.getTestCaseNames(Test), []) | |
973 | - | |
974 | - # "Return a sorted sequence of method names found within testCaseClass" | |
975 | - # | |
976 | - # Are not-TestCases handled gracefully? | |
977 | - # | |
978 | - # XXX This should raise a TypeError, not return a list | |
979 | - # | |
980 | - # XXX It's too late in the 2.5 release cycle to fix this, but it should | |
981 | - # probably be revisited for 2.6 | |
982 | - def test_getTestCaseNames__not_a_TestCase(self): | |
983 | - class BadCase(int): | |
984 | - def test_foo(self): | |
985 | - pass | |
986 | - | |
987 | - loader = unittest.TestLoader() | |
988 | - names = loader.getTestCaseNames(BadCase) | |
989 | - | |
990 | - self.assertEqual(names, ['test_foo']) | |
991 | - | |
992 | - # "Return a sorted sequence of method names found within testCaseClass" | |
993 | - # | |
994 | - # Make sure inherited names are handled. | |
995 | - # | |
996 | - # TestP.foobar is defined to make sure getTestCaseNames() respects | |
997 | - # loader.testMethodPrefix | |
998 | - def test_getTestCaseNames__inheritance(self): | |
999 | - class TestP(unittest.TestCase): | |
1000 | - def test_1(self): pass | |
1001 | - def test_2(self): pass | |
1002 | - def foobar(self): pass | |
1003 | - | |
1004 | - class TestC(TestP): | |
1005 | - def test_1(self): pass | |
1006 | - def test_3(self): pass | |
1007 | - | |
1008 | - loader = unittest.TestLoader() | |
1009 | - | |
1010 | - names = ['test_1', 'test_2', 'test_3'] | |
1011 | - self.assertEqual(loader.getTestCaseNames(TestC), names) | |
1012 | - | |
1013 | - ################################################################ | |
1014 | - ### /Tests for TestLoader.getTestCaseNames() | |
1015 | - | |
1016 | - ### Tests for TestLoader.testMethodPrefix | |
1017 | - ################################################################ | |
1018 | - | |
1019 | - # "String giving the prefix of method names which will be interpreted as | |
1020 | - # test methods" | |
1021 | - # | |
1022 | - # Implicit in the documentation is that testMethodPrefix is respected by | |
1023 | - # all loadTestsFrom* methods. | |
1024 | - def test_testMethodPrefix__loadTestsFromTestCase(self): | |
1025 | - class Foo(unittest.TestCase): | |
1026 | - def test_1(self): pass | |
1027 | - def test_2(self): pass | |
1028 | - def foo_bar(self): pass | |
1029 | - | |
1030 | - tests_1 = unittest.TestSuite([Foo('foo_bar')]) | |
1031 | - tests_2 = unittest.TestSuite([Foo('test_1'), Foo('test_2')]) | |
1032 | - | |
1033 | - loader = unittest.TestLoader() | |
1034 | - loader.testMethodPrefix = 'foo' | |
1035 | - self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_1) | |
1036 | - | |
1037 | - loader.testMethodPrefix = 'test' | |
1038 | - self.assertEqual(loader.loadTestsFromTestCase(Foo), tests_2) | |
1039 | - | |
1040 | - # "String giving the prefix of method names which will be interpreted as | |
1041 | - # test methods" | |
1042 | - # | |
1043 | - # Implicit in the documentation is that testMethodPrefix is respected by | |
1044 | - # all loadTestsFrom* methods. | |
1045 | - def test_testMethodPrefix__loadTestsFromModule(self): | |
1046 | - m = types.ModuleType('m') | |
1047 | - class Foo(unittest.TestCase): | |
1048 | - def test_1(self): pass | |
1049 | - def test_2(self): pass | |
1050 | - def foo_bar(self): pass | |
1051 | - m.Foo = Foo | |
1052 | - | |
1053 | - tests_1 = [unittest.TestSuite([Foo('foo_bar')])] | |
1054 | - tests_2 = [unittest.TestSuite([Foo('test_1'), Foo('test_2')])] | |
1055 | - | |
1056 | - loader = unittest.TestLoader() | |
1057 | - loader.testMethodPrefix = 'foo' | |
1058 | - self.assertEqual(list(loader.loadTestsFromModule(m)), tests_1) | |
1059 |