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 (at] 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 # using str() because of cStringIO's Unicode undesired Unicode behavior. 29 infile = StringIO(str(input)) 30 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') 41 42 return (outfile.getvalue(), len(input)) 43 44 def 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 64 infile = StringIO(str(input)) 65 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 96 class Codec(codecs.Codec): 97 98 def encode(self,input,errors='strict'): 99 return uu_encode(input,errors) 100 101 def decode(self,input,errors='strict'): 102 return uu_decode(input,errors) 103 104 class IncrementalEncoder(codecs.IncrementalEncoder): 105 def encode(self, input, final=False): 106 return uu_encode(input, self.errors)[0] 107 108 class IncrementalDecoder(codecs.IncrementalDecoder): 109 def decode(self, input, final=False): 110 return uu_decode(input, self.errors)[0] 111 112 class StreamWriter(Codec,codecs.StreamWriter): 113 pass 114 115 class StreamReader(Codec,codecs.StreamReader): 116 pass 117 118 ### encodings module API 119 120 def getregentry(): 121 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 ) 130