""" This module provides methods for dynamically creating flow and group record classes. """ def get_record_class(attributes, types=None, default_vals=None): ''' Creates a record class for given attribute names. Arguments: attributes - a sequence of attribute names types - optional sequence of attribute types, which correspond to the attribute names in attributes. Types may be of any type, and are not used by the Record class, but are useful for external storage, where data type has to be predetermined. default_val - a sequence of default values which correspond to the attribute names in attributes Lists are used instead of dictionaries because the order may be important. Return: Record class which has attributes with the names given by attributes list. The class uses __slots__ to lower memory usage as potentially millions of instance will be present during runtime. The class has a constructor, which takes as argument values for the attributes ordered the same way as in the attributes list. If default values are specified there is a default(no argument) constructor as well. NOTE that this method returns a class not an instance. Raises: ValueError if number of types or default values doesn't match number of attributes. ''' if default_vals and len(attributes) != len(default_vals): raise ValueError( "Number of attributes(%d) and number of default values(%d)"% (len(attributes),len(default_vals))+" don't match") if types and len(attributes) != len(types): raise ValueError( "Number of attributes(%d) and number of default types(%d)"% (len(attributes),len(default_vals))+" don't match") elif types: types_dict = dict(zip(attributes, types)) else: types_dict = {} class Record(object): ''' Record class contains flow or group record information. It uses __slots__ to save memory because potentially millions of FlowRecords will be used during run time. Attributes: attribute names are specified in cls.__slots__ defaults - contains the default values for attributes used with default constructor. attr_types - contains a dictionary of the types of the attributes. Methods: __init__ - when defaults is specified __init__() creates an object with default values. If no defaults are specified during class creation __init__() raises TypeError. __init__(*args) takes exactly the same number of arguments as the classes' number of attributes, and creates new instance with the given values. Argument order corresponds to the order of attributes in cls.__slots__ ''' # set slots to conserve memory # copy ([:]) don't reference to protect from unexpected changes __slots__ = attributes[:] attr_types = types_dict num_of_fields = len(__slots__) defaults = default_vals[:] if default_vals else None def __init__(self, *args): num_args = len(args) if num_args == self.num_of_fields: for name, value in zip(self.__slots__,args): setattr(self, name, value) elif num_args == 0 and self.defaults != None: for name, value in zip(self.__slots__,self.defaults): setattr(self, name, value) elif self.defaults == None: raise TypeError( "__init__() takes %d arguments (%d given)"% ( self.num_of_fields + 1, num_args+1)) else: raise TypeError( "__init__() takes either 1 or %d arguments (%d given)"% ( self.num_of_fields + 1, num_args+1)) def tuple(self): return tuple(getattr(self, field) for field in self.slots) def __repr__(self): res = "Recod(" for field in self.__slots__: val = getattr(self, field) if type(val) is str: val = "'" + str(val) + "'" else: val = str(val) res += val + ", " res =res[:-2] + ")" return res def __str__(self): res = "Recod: " for field in self.__slots__: val = getattr(self, field) res += field + "->" + str(val) + ", " res =res[:-2] return res return Record class RecordReader(object): def __init__(self, reader_object): self.reader = reader_object #print self.reader.fields self.Record = get_record_class(self.reader.fields) def __iter__(self): for tuple in self.reader: yield self.Record(*tuple) def read_rows_list(self, rows_list): for tuple in self.reader.read_rows_list(rows_list): yield self.Record(*tuple) def read_row(self, row_n): tup = self.reader.read_row(row_n) return self.Record(*tup) #from flowy import pytables #ptread = pytables.FlowRecordsTable("../testFT.h5" ) #rr = RecordReader(ptread) #for i in rr: # print i.dOctets # # #FlowRecord = get_record_class(["a","b"],["str","uint"],[1,6]) # #def printSth(self): # print "sth" # #FlowRecord.p = printSth # #x = FlowRecord(1,6) # # #print x.a, x.b #print x.__slots__ # #t = FlowRecord() #print t.a #t.p()