Home | History | Annotate | Download | only in encodings
      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