#NEWLINE# def create_attr_list_type( class_name , * fields ) : #NEWLINE# #INDENT# 'Create a new attr_list_type which is a class offering get and set\n    methods which is capable of serializing and deserializing itself from\n    netlink message.  The fields are a bunch of tuples of name and a class\n    which should provide pack and unpack (except for in the case where we\n    know it will be used exclusively for serialization or deserialization).\n    attr_list_types can be used as packers in other attr_list_types.  The\n    names and packers of the field should be taken from the appropriate\n    linux kernel header and source files.\n    ' #NEWLINE# name_to_key = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# key_to_name = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# key_to_packer = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# for ( i , ( name , packer ) ) in enumerate ( fields ) : #NEWLINE# #INDENT# key = ( i + 1 ) #NEWLINE# name_to_key [ name . upper ( ) ] = key #NEWLINE# key_to_name [ key ] = name #NEWLINE# key_to_packer [ key ] = packer #NEWLINE# #UNINDENT# class AttrListType ( AttrListPacker ) : #NEWLINE# #INDENT# def __init__( self , **kwargs ) : #NEWLINE# #INDENT# self . attrs = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# for ( k , v ) in kwargs . items ( ) : #NEWLINE# #INDENT# if ( v is not None ) : #NEWLINE# #INDENT# self . set ( k , v ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# def set( self , key , value ) : #NEWLINE# #INDENT# if ( not isinstance ( key , int ) ) : #NEWLINE# #INDENT# key = name_to_key [ key . upper ( ) ] #NEWLINE# #UNINDENT# self . attrs [ key ] = value #NEWLINE# #UNINDENT# def get( self , key , default = _unset ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# if ( not isinstance ( key , int ) ) : #NEWLINE# #INDENT# key = name_to_key [ key . upper ( ) ] #NEWLINE# #UNINDENT# return self . attrs [ key ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# if ( default is not _unset ) : #NEWLINE# #INDENT# return default #NEWLINE# #UNINDENT# raise #NEWLINE# #UNINDENT# #UNINDENT# def __repr__( self ) : #NEWLINE# #INDENT# attrs = [ ( '%s=%s' % ( key_to_name [ k ] . lower ( ) , repr ( v ) ) ) for ( k , v ) in self . attrs . items ( ) ] #NEWLINE# return ( '%s(%s)' % ( class_name , ', ' . join ( attrs ) ) ) #NEWLINE# #UNINDENT# @ staticmethod #NEWLINE# def pack( attr_list ) : #NEWLINE# #INDENT# packed = array . array ( str ( 'B' ) ) #NEWLINE# for ( k , v ) in attr_list . attrs . items ( ) : #NEWLINE# #INDENT# if ( key_to_packer [ k ] == RecursiveSelf ) : #NEWLINE# #INDENT# x = AttrListType . pack ( v ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# x = key_to_packer [ k ] . pack ( v ) #NEWLINE# #UNINDENT# alen = ( len ( x ) + 4 ) #NEWLINE# packed . fromstring ( struct . pack ( str ( '=HH' ) , alen , k ) ) #NEWLINE# packed . fromstring ( x ) #NEWLINE# packed . fromstring ( ( '\x00' * ( ( 4 - ( len ( x ) % 4 ) ) & 3 ) ) ) #NEWLINE# #UNINDENT# return packed #NEWLINE# #UNINDENT# @ staticmethod #NEWLINE# def unpack( data ) : #NEWLINE# #INDENT# global global_nest #NEWLINE# attr_list = AttrListType ( ) #NEWLINE# while ( len ( data ) > 0 ) : #NEWLINE# #INDENT# ( alen , k ) = struct . unpack ( str ( '=HH' ) , data [ : 4 ] ) #NEWLINE# alen = ( alen & 32767 ) #NEWLINE# if ( key_to_packer [ k ] == RecursiveSelf ) : #NEWLINE# #INDENT# v = AttrListType . unpack ( data [ 4 : alen ] ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# v = key_to_packer [ k ] . unpack ( data [ 4 : alen ] ) #NEWLINE# #UNINDENT# attr_list . set ( k , v ) #NEWLINE# data = data [ ( ( alen + 3 ) & ( ~ 3 ) ) : ] #NEWLINE# #UNINDENT# return attr_list #NEWLINE# #UNINDENT# #UNINDENT# return AttrListType