Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | """ Python 'uu_codec' Codec - UU content transfer 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). Some details were | |
7 | adapted from uu.py which was written by Lance Ellinghouse and | |
8 | modified by Jack Jansen and Fredrik Lundh. | |
9 | ||
10 | """ | |
11 | import codecs, binascii | |
12 | ||
13 | ### Codec APIs | |
14 | ||
15 | def uu_encode(input,errors='strict',filename='<data>',mode=0666): | |
16 | ||
17 | """ Encodes the object input and returns a tuple (output | |
18 | object, length consumed). | |
19 | ||
20 | errors defines the error handling to apply. It defaults to | |
21 | 'strict' handling which is the only currently supported | |
22 | error handling for this codec. | |
23 | ||
24 | """ | |
25 | assert errors == 'strict' | |
26 | from cStringIO import StringIO | |
27 | from binascii import b2a_uu | |
28 | infile = StringIO(input) | |
29 | outfile = StringIO() | |
30 | read = infile.read | |
31 | write = outfile.write | |
32 | ||
33 | # Encode | |
34 | write('begin %o %s\n' % (mode & 0777, filename)) | |
35 | chunk = read(45) | |
36 | while chunk: | |
37 | write(b2a_uu(chunk)) | |
38 | chunk = read(45) | |
39 | write(' \nend\n') | |
40 | ||
41 | return (outfile.getvalue(), len(input)) | |
42 | ||
43 | def uu_decode(input,errors='strict'): | |
44 | ||
45 | """ Decodes the object input and returns a tuple (output | |
46 | object, length consumed). | |
47 | ||
48 | input must be an object which provides the bf_getreadbuf | |
49 | buffer slot. Python strings, buffer objects and memory | |
50 | mapped files are examples of objects providing this slot. | |
51 | ||
52 | errors defines the error handling to apply. It defaults to | |
53 | 'strict' handling which is the only currently supported | |
54 | error handling for this codec. | |
55 | ||
56 | Note: filename and file mode information in the input data is | |
57 | ignored. | |
58 | ||
59 | """ | |
60 | assert errors == 'strict' | |
61 | from cStringIO import StringIO | |
62 | from binascii import a2b_uu | |
63 | infile = StringIO(input) | |
64 | outfile = StringIO() | |
65 | readline = infile.readline | |
66 | write = outfile.write | |
67 | ||
68 | # Find start of encoded data | |
69 | while 1: | |
70 | s = readline() | |
71 | if not s: | |
72 | raise ValueError, 'Missing "begin" line in input data' | |
73 | if s[:5] == 'begin': | |
74 | break | |
75 | ||
76 | # Decode | |
77 | while 1: | |
78 | s = readline() | |
79 | if not s or \ | |
80 | s == 'end\n': | |
81 | break | |
82 | try: | |
83 | data = a2b_uu(s) | |
84 | except binascii.Error, v: | |
85 | # Workaround for broken uuencoders by /Fredrik Lundh | |
86 | nbytes = (((ord(s[0])-32) & 63) * 4 + 5) / 3 | |
87 | data = a2b_uu(s[:nbytes]) | |
88 | #sys.stderr.write("Warning: %s\n" % str(v)) | |
89 | write(data) | |
90 | if not s: | |
91 | raise ValueError, 'Truncated input data' | |
92 | ||
93 | return (outfile.getvalue(), len(input)) | |
94 | ||
95 | class Codec(codecs.Codec): | |
96 | ||
97 | def encode(self,input,errors='strict'): | |
98 | return uu_encode(input,errors) | |
99 | def decode(self,input,errors='strict'): | |
100 | return uu_decode(input,errors) | |
101 | ||
102 | class StreamWriter(Codec,codecs.StreamWriter): | |
103 | pass | |
104 | ||
105 | class StreamReader(Codec,codecs.StreamReader): | |
106 | pass | |
107 | ||
108 | ### encodings module API | |
109 | ||
110 | def getregentry(): | |
111 | ||
112 | return (uu_encode,uu_decode,StreamReader,StreamWriter) |