home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / util / packable.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  7.3 KB  |  166 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from primitives import to_hex
  5. from struct import Struct
  6. from itertools import izip
  7. from logging import getLogger
  8. log = getLogger('packable')
  9. __all__ = [
  10.     'Packable']
  11.  
  12. def debugline(fc):
  13.     return '  File "%s", line %d, in %s' % (fc.co_filename, fc.co_firstlineno, fc.co_name)
  14.  
  15.  
  16. class PackableMeta(type):
  17.     
  18.     def __new__(meta, classname, bases, newattrs):
  19.         cls = super(PackableMeta, meta).__new__(meta, classname, bases, newattrs)
  20.         if 'fmt' not in newattrs:
  21.             return cls
  22.         
  23.         byteorder = newattrs.pop('byteorder', '!')
  24.         fmt = newattrs.pop('fmt')
  25.         __slots__ = list(fmt[::2])
  26.         _struct = Struct(byteorder + ''.join(fmt[1::2]))
  27.         _invars = newattrs.pop('invars', [])
  28.         if not isinstance(_invars, (list, tuple)):
  29.             _invars = [
  30.                 _invars]
  31.         
  32.         fmts = ''.join((lambda .0: for i, j in .0:
  33. '\t%s\t\t%s\n' % (i, j))(izip(fmt[::2], fmt[1::2])))
  34.         cls.__doc__ = 'Constructs a %s, taking sequential arguments in the order they were\nspecified by the format description (or named keyword arguments!):\n\n%s' % (classname, fmts)
  35.         
  36.         def checkinvars(cls, o):
  37.             for invar in cls._invars:
  38.                 if not invar(o):
  39.                     fc = invar.func_code
  40.                     raise AssertionError('Invariant failed after unpacking:\n%s' % debugline(fc))
  41.                     continue
  42.             
  43.  
  44.         
  45.         def unpack(cls, data):
  46.             sz = cls._struct.size
  47.             o = cls(*cls._struct.unpack(data[:sz]))
  48.             
  49.             try:
  50.                 checkinvars(cls, o)
  51.             except AssertionError:
  52.                 log.error('wrong data: %s', to_hex(data))
  53.                 raise 
  54.  
  55.             return (o, data[sz:])
  56.  
  57.         unpack = (classmethod,)(unpack)
  58.         
  59.         def pack(self):
  60.             checkinvars(self.__class__, self)
  61.             attrs = [ getattr(self, field) for field in self.__slots__ ]
  62.             return self._struct.pack(*attrs)
  63.  
  64.         
  65.         def __eq__(self, other):
  66.             for attr in self.__slots__:
  67.                 if getattr(other, attr, sentinel) != getattr(self, attr):
  68.                     return False
  69.                     continue
  70.             
  71.             return True
  72.  
  73.         
  74.         __len__ = lambda self: self._struct.size
  75.         
  76.         __iter__ = lambda self: (lambda .0: for s in .0:
  77. (s, getattr(self, s)))(self.__slots__)
  78.  
  79.         __str__ = pack
  80.         localdict = locals()
  81.         classattrs = '__slots__ _struct pack unpack __len__\n                        _invars __iter__ __str__ __eq__'.split()
  82.         for a in classattrs:
  83.             setattr(cls, a, localdict[a])
  84.         
  85.         return cls
  86.  
  87.  
  88.  
  89. class Packable(object):
  90.     __metaclass__ = PackableMeta
  91.     
  92.     def __init__(self, *a, **kw):
  93.         i = -1
  94.         for i, d in enumerate(a):
  95.             setattr(self, self.__slots__[i], d)
  96.         
  97.         for f in self.__slots__[i + 1:]:
  98.             setattr(self, f, 0)
  99.         
  100.         for k in kw:
  101.             setattr(self, k, kw[k])
  102.         
  103.  
  104.     
  105.     def __repr__(self):
  106.         return '<%s %s>' % (type(self).__name__, ' '.join((lambda .0: for i in .0:
  107. '%s=%r' % i)(self)))
  108.  
  109.  
  110. from math import log as _log, floor, ceil
  111.  
  112. def num_bits(i):
  113.     return floor(_log(i, 2)) + 1
  114.  
  115.  
  116. def num_bytes(i):
  117.     if i in (0, 1):
  118.         return 1
  119.     else:
  120.         return int(ceil(pow(2, num_bits(num_bits(i) - 1)) / 8))
  121.  
  122.  
  123. def make_packable(info):
  124.     (names, values) = zip(*sorted(info, key = (lambda x: type(x[1]))))
  125.     type_size = {
  126.         str: (lambda s: len(s)),
  127.         unicode: (lambda u: 2 * len(u)),
  128.         int: (lambda i: pow(2, num_bits(num_bits(i) - 1)) / 8),
  129.         bool: (lambda b: 0) }
  130.     
  131.     get_size = lambda x: type_size[type(x)](x)
  132.     sizes = [ get_size(v) for v in values ]
  133.     ints = bools_to_ints(filter((lambda x: type(x) is bool), values))
  134.     size_in_bytes = sum(sizes) + len(ints) * 4
  135.  
  136.  
  137. def bools_to_ints(bools):
  138.     nums = []
  139.     num_ints = ceil(len(bools) / 32)
  140.     for i in range(num_ints):
  141.         num = 0
  142.         for i in range(len(bools[i * 32:(i + 1) * 32])):
  143.             num |= bools[i] * pow(2, i % 32)
  144.         
  145.         nums.append(num)
  146.     
  147.     return nums
  148.  
  149.  
  150. def main():
  151.     
  152.     class Meep(Packable):
  153.         fmt = ('version', '4s', 'length', 'H', 'name', '3s')
  154.         invars = [
  155.             (lambda o: o.version == 'OFT2')]
  156.  
  157.     m = Meep('OFT2', 2, 'abc')
  158.     print repr(str(Meep.unpack(m.pack())[0]))
  159.     print m.__class__.__name__
  160.     print m.__doc__
  161.     print repr(m)
  162.  
  163. if __name__ == '__main__':
  164.     main()
  165.  
  166.