blob: fb03758171d1218ad023f7a092584baa28111883 [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
Georg Brandl4cdceac2007-09-03 07:16:46 +000028 # using str() because of cStringIO's Unicode undesired Unicode behavior.
29 infile = StringIO(str(input))
Marc-André Lemburg2d920412001-05-15 12:00:02 +000030 outfile = StringIO()
31 read = infile.read
32 write = outfile.write
33
34 # Encode
35 write('begin %o %s\n' % (mode & 0777, filename))
36 chunk = read(45)
37 while chunk:
38 write(b2a_uu(chunk))
39 chunk = read(45)
40 write(' \nend\n')
Tim Peters469cdad2002-08-08 20:19:19 +000041
Marc-André Lemburg2d920412001-05-15 12:00:02 +000042 return (outfile.getvalue(), len(input))
43
44def uu_decode(input,errors='strict'):
45
46 """ Decodes the object input and returns a tuple (output
47 object, length consumed).
48
49 input must be an object which provides the bf_getreadbuf
50 buffer slot. Python strings, buffer objects and memory
51 mapped files are examples of objects providing this slot.
52
53 errors defines the error handling to apply. It defaults to
54 'strict' handling which is the only currently supported
55 error handling for this codec.
56
57 Note: filename and file mode information in the input data is
58 ignored.
59
60 """
61 assert errors == 'strict'
62 from cStringIO import StringIO
63 from binascii import a2b_uu
Georg Brandl4cdceac2007-09-03 07:16:46 +000064 infile = StringIO(str(input))
Marc-André Lemburg2d920412001-05-15 12:00:02 +000065 outfile = StringIO()
66 readline = infile.readline
67 write = outfile.write
68
69 # Find start of encoded data
70 while 1:
71 s = readline()
72 if not s:
73 raise ValueError, 'Missing "begin" line in input data'
74 if s[:5] == 'begin':
75 break
76
77 # Decode
78 while 1:
79 s = readline()
80 if not s or \
81 s == 'end\n':
82 break
83 try:
84 data = a2b_uu(s)
85 except binascii.Error, v:
86 # Workaround for broken uuencoders by /Fredrik Lundh
87 nbytes = (((ord(s[0])-32) & 63) * 4 + 5) / 3
88 data = a2b_uu(s[:nbytes])
89 #sys.stderr.write("Warning: %s\n" % str(v))
90 write(data)
91 if not s:
92 raise ValueError, 'Truncated input data'
93
94 return (outfile.getvalue(), len(input))
95
96class Codec(codecs.Codec):
97
Marc-André Lemburg26e3b682001-09-20 10:33:38 +000098 def encode(self,input,errors='strict'):
99 return uu_encode(input,errors)
Walter Dörwaldabb02e52006-03-15 11:35:15 +0000100
Marc-André Lemburg26e3b682001-09-20 10:33:38 +0000101 def decode(self,input,errors='strict'):
102 return uu_decode(input,errors)
Tim Peters469cdad2002-08-08 20:19:19 +0000103
Walter Dörwaldabb02e52006-03-15 11:35:15 +0000104class IncrementalEncoder(codecs.IncrementalEncoder):
105 def encode(self, input, final=False):
Walter Dörwald6b6e2bb2006-06-13 12:02:12 +0000106 return uu_encode(input, self.errors)[0]
Walter Dörwaldabb02e52006-03-15 11:35:15 +0000107
108class IncrementalDecoder(codecs.IncrementalDecoder):
109 def decode(self, input, final=False):
Walter Dörwald6b6e2bb2006-06-13 12:02:12 +0000110 return uu_decode(input, self.errors)[0]
Walter Dörwaldabb02e52006-03-15 11:35:15 +0000111
Marc-André Lemburg2d920412001-05-15 12:00:02 +0000112class StreamWriter(Codec,codecs.StreamWriter):
113 pass
Tim Peters469cdad2002-08-08 20:19:19 +0000114
Marc-André Lemburg2d920412001-05-15 12:00:02 +0000115class StreamReader(Codec,codecs.StreamReader):
116 pass
117
118### encodings module API
119
120def getregentry():
Walter Dörwaldabb02e52006-03-15 11:35:15 +0000121 return codecs.CodecInfo(
122 name='uu',
123 encode=uu_encode,
124 decode=uu_decode,
125 incrementalencoder=IncrementalEncoder,
126 incrementaldecoder=IncrementalDecoder,
127 streamreader=StreamReader,
128 streamwriter=StreamWriter,
129 )