blob: a70ff9e8efd14598e5f6c42b8c29a6b56c10f4ae [file] [log] [blame]
Marc-André Lemburg2d920412001-05-15 12:00:02 +00001""" 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"""
11import codecs, binascii
12
13### Codec APIs
14
15def 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')
Tim Peters469cdad2002-08-08 20:19:19 +000040
Marc-André Lemburg2d920412001-05-15 12:00:02 +000041 return (outfile.getvalue(), len(input))
42
43def 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
95class Codec(codecs.Codec):
96
Marc-André Lemburg26e3b682001-09-20 10:33:38 +000097 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)
Tim Peters469cdad2002-08-08 20:19:19 +0000101
Marc-André Lemburg2d920412001-05-15 12:00:02 +0000102class StreamWriter(Codec,codecs.StreamWriter):
103 pass
Tim Peters469cdad2002-08-08 20:19:19 +0000104
Marc-André Lemburg2d920412001-05-15 12:00:02 +0000105class StreamReader(Codec,codecs.StreamReader):
106 pass
107
108### encodings module API
109
110def getregentry():
111
112 return (uu_encode,uu_decode,StreamReader,StreamWriter)