home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / util / packable.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  7.4 KB  |  166 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  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.         byteorder = newattrs.pop('byteorder', '!')
  23.         fmt = newattrs.pop('fmt')
  24.         __slots__ = list(fmt[::2])
  25.         _struct = Struct(byteorder + ''.join(fmt[1::2]))
  26.         _invars = newattrs.pop('invars', [])
  27.         if not isinstance(_invars, (list, tuple)):
  28.             _invars = [
  29.                 _invars]
  30.         
  31.         fmts = ''.join((lambda .0: for i, j in .0:
  32. '\t%s\t\t%s\n' % (i, j))(izip(fmt[::2], fmt[1::2])))
  33.         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)
  34.         
  35.         def checkinvars(cls, o):
  36.             for invar in cls._invars:
  37.                 if not invar(o):
  38.                     fc = invar.func_code
  39.                     raise AssertionError('Invariant failed after unpacking:\n%s' % debugline(fc))
  40.                 invar(o)
  41.             
  42.  
  43.         
  44.         def unpack(cls, data):
  45.             sz = cls._struct.size
  46.             o = cls(*cls._struct.unpack(data[:sz]))
  47.             
  48.             try:
  49.                 checkinvars(cls, o)
  50.             except AssertionError:
  51.                 log.error('wrong data: %s', to_hex(data))
  52.                 raise 
  53.  
  54.             return (o, data[sz:])
  55.  
  56.         unpack = (classmethod,)(unpack)
  57.         
  58.         def pack(self):
  59.             checkinvars(self.__class__, self)
  60.             attrs = [ getattr(self, field) for field in self.__slots__ ]
  61.             return self._struct.pack(*attrs)
  62.  
  63.         
  64.         def __eq__(self, other):
  65.             for attr in self.__slots__:
  66.                 if getattr(other, attr, sentinel) != getattr(self, attr):
  67.                     return False
  68.             
  69.             return True
  70.  
  71.         
  72.         __len__ = lambda self: self.size
  73.         
  74.         __iter__ = lambda self: (lambda .0: for s in .0:
  75. (s, getattr(self, s)))(self.__slots__)
  76.  
  77.         __str__ = pack
  78.         
  79.         copy = lambda self: cls.unpack(self.pack())[0]
  80.         size = _struct.size
  81.         localdict = locals()
  82.         classattrs = '__slots__ _struct pack unpack __len__\n                        _invars __iter__ __str__ __eq__ copy size'.split()
  83.         for a in classattrs:
  84.             setattr(cls, a, localdict[a])
  85.         
  86.         return cls
  87.  
  88.  
  89.  
  90. class Packable(object):
  91.     __metaclass__ = PackableMeta
  92.     
  93.     def __init__(self, *a, **kw):
  94.         i = -1
  95.         for i, d in enumerate(a):
  96.             setattr(self, self.__slots__[i], d)
  97.         
  98.         for f in self.__slots__[i + 1:]:
  99.             setattr(self, f, 0)
  100.         
  101.         for k in kw:
  102.             setattr(self, k, kw[k])
  103.         
  104.  
  105.     
  106.     def __repr__(self):
  107.         return '<%s %s>' % (type(self).__name__, ' '.join((lambda .0: for i in .0:
  108. '%s=%r' % i)(self)))
  109.  
  110.  
  111. from math import log as _log, floor, ceil
  112.  
  113. def num_bits(i):
  114.     return floor(_log(i, 2)) + 1
  115.  
  116.  
  117. def num_bytes(i):
  118.     if i in (0, 1):
  119.         return 1
  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.