text: #!/usr/bin/env python
  
  import struct
  import unittest
  
  #-----------------------------------------------------------------------------
  #: enable verbose print statements.
  DEBUG = True
  
  #: struct format lookup for specific word sizes.
  STRUCT_FMT = {
      8  : 'B',   # unsigned char
      16 : 'H',   # unsigned short
      32 : 'I',   # unsigned int
  }
  
  #-----------------------------------------------------------------------------
  def int_to_words(int_val, num_words=4, word_size=32):
      """
      @param int_val: an arbitrary length Python integer to be split up.
          Network byte order is assumed. Raises an IndexError if width of
          integer (in bits) exceeds word_size * num_words.
  
      @param num_words: number of words expected in return value tuple.
  
      @param word_size: size/width of individual words (in bits).
  
      @return: a list of fixed width words based on provided parameters.
      """
      max_int = 2 ** (word_size*num_words) - 1
      max_word_size = 2 ** word_size - 1
  
      if not 0 <= int_val <= max_int:
          raise IndexError('integer %r is out of bounds!' % hex(int_val))
  
      words = []
      for _ in range(num_words):
          word = int_val & max_word_size
          words.append(int(word))
          int_val >>= word_size
      words.reverse()
  
      return words
  
  #-----------------------------------------------------------------------------
  def int_to_packed(int_val, width=128, word_size=32):
      """
      @param int_val: an arbitrary sized Python integer to be packed.
  
      @param width: expected maximum with of an integer. Can be any size but
          should be divide by word_size without a remainder.
  
      @param word_size: size/width of individual words (in bits).
          Valid sizes are 8, 16 and 32 bits.
  
      @return: a (network byte order) packed string equivalent to integer value.
      """
      num_words = width / word_size
      words = int_to_words(int_val, num_words, word_size)
  
      try:
          fmt = '>%d%s' % (num_words, STRUCT_FMT[word_size])
          #DEBUG: print 'format:', fmt
      except KeyError:
          raise ValueError('unsupported word size: %d!' % word_size)
  
      return struct.pack(fmt, *words)
  
  #-----------------------------------------------------------------------------
  def packed_to_int(packed_int, width=128, word_size=32):
      """
      @param packed_int: a packed string to be converted to an abritrary size
          Python integer. Network byte order is assumed.
  
      @param width: expected maximum width of return value integer. Can be any
          size but should divide by word_size equally without remainder.
  
      @param word_size: size/width of individual words (in bits).
          Valid sizes are 8, 16 and 32 bits.
  
      @return: an arbitrary sized Python integer.
      """
      num_words = width / word_size
  
      try:
          fmt = '>%d%s' % (num_words, STRUCT_FMT[word_size])
          #DEBUG: print 'format:', fmt
      except KeyError:
          raise ValueError('unsupported word size: %d!' % word_size)
  
      words = list(struct.unpack(fmt, packed_int))
      words.reverse()
  
      int_val = 0
      for i, num in enumerate(words):
          word = num
          word = word << word_size * i
          int_val = int_val | word
  
      return int_val
  
  #-----------------------------------------------------------------------------
  class NetworkAddressTests(unittest.TestCase):
      """Example test case using various network address types"""
      def debug(self, val, expect_val_packed, actual_val_packed, new_val):
          print 'original int          :', hex(val)
          print 'packed int (expected) : %r' % expect_val_packed
          print 'packed int (actual)   : %r' % actual_val_packed
          print 'unpacked int          :', hex(new_val)
          print
  
      def testIPv4(self):
          """IP version 4 address test"""
          val = 0xfffefffe
          expect_val_packed = '\xff\xfe\xff\xfe'
          actual_val_packed = int_to_packed(val, width=32, word_size=8)
          new_val = packed_to_int(actual_val_packed, width=32, word_size=8)
          self.assertEqual(val, new_val)
          self.assertEqual(expect_val_packed, actual_val_packed)
  
          if DEBUG:
              print 'IPv4'
              self.debug(val, expect_val_packed, actual_val_packed, new_val)
  
      def testMAC(self):
          """MAC address test"""
          val = 0xfffefffefffe
          expect_val_packed = '\xff\xfe\xff\xfe\xff\xfe'
          actual_val_packed = int_to_packed(val, width=48, word_size=8)
          new_val = packed_to_int(actual_val_packed, width=48, word_size=8)
          self.assertEqual(val, new_val)
          self.assertEqual(expect_val_packed, actual_val_packed)
  
          if DEBUG:
              print 'MAC'
              self.debug(val, expect_val_packed, actual_val_packed, new_val)
  
      def testIPv6(self):
          """IP version 6 address test"""
          val = 0xfffefffefffefffefffefffefffefffe
          expect_val_packed = '\xff\xfe\xff\xfe\xff\xfe\xff\xfe' \
                                '\xff\xfe\xff\xfe\xff\xfe\xff\xfe'
          actual_val_packed = int_to_packed(val, width=128, word_size=32)
          new_val = packed_to_int(actual_val_packed, width=128, word_size=32)
          self.assertEqual(val, new_val)
          self.assertEqual(expect_val_packed, actual_val_packed)
  
          if DEBUG:
              print 'IPv6'
              self.debug(val, expect_val_packed, actual_val_packed, new_val)
  
  #-----------------------------------------------------------------------------
  if __name__ == '__main__':
      unittest.main()
  