/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/table.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/table.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 806 by jan, Fri May 2 16:43:59 2003 UTC revision 907 by bh, Fri May 16 15:01:04 2003 UTC
# Line 12  Classes for handling tables of data. Line 12  Classes for handling tables of data.
12    
13  __version__ = "$Revision$"  __version__ = "$Revision$"
14    
15    import inspect
16    import warnings
17    
18  import dbflib  import dbflib
19    
20  # the field types supported by a Table instance.  # the field types supported by a Table instance.
# Line 25  dbflib_fieldtypes = {dbflib.FTString: FI Line 28  dbflib_fieldtypes = {dbflib.FTString: FI
28                       dbflib.FTInteger: FIELDTYPE_INT,                       dbflib.FTInteger: FIELDTYPE_INT,
29                       dbflib.FTDouble: FIELDTYPE_DOUBLE}                       dbflib.FTDouble: FIELDTYPE_DOUBLE}
30    
 class MemoryTable:  
31    
32      """Quite simple table implementation that operates on a list of tuples.  class OldTableInterfaceMixin:
     All of the data are kept in the memory."""  
33    
34      def __init__(self, fields, data):      """Mixin to implement the old table interface using the new one"""
         """Initialize the MemoryTable  
35    
36          Parameters:      def __deprecation_warning(self):
37          fields -- List of (name, field_type) pairs          """Issue a DeprecationWarning for code hat uses the old interface"""
38          data -- List of tuples, one for each row of data          callername = inspect.currentframe().f_back.f_code.co_name
39          """          warnings.warn("The %s method of the old table interface"
40          self.fields = fields                        " is deprecated" % callername,
41          self.data = data                        DeprecationWarning, stacklevel = 3)
42    
43        def record_count(self):
44            self.__deprecation_warning()
45            return self.NumRows()
46    
47      def field_count(self):      def field_count(self):
48          return len(self.fields)          self.__deprecation_warning()
49            return self.NumColumns()
50    
51      def field_info(self, index):      def field_info(self, field):
52          name, type = self.fields[index]          """Return a tuple (type, name, width, prec) for the field no. field
         return (type, name)  
53    
54      def record_count(self):          type is the data type of the field, name the name, width the
55          return len(self.data)          field width in characters and prec the decimal precision. width
56            and prec will be zero if the information returned by the Column
57            method doesn't provide values for them.
58            """
59            self.__deprecation_warning()
60            col = self.Column(field)
61            return (col.type, col.name,
62                   getattr(col, "width", 0), getattr(col, "prec", 0))
63    
64        def field_info_by_name(self, col):
65            self.__deprecation_warning()
66            try:
67                return self.field_info(col)
68            except KeyError:
69                # FIXME: It may be that field_info raises other exceptions
70                # when the name is not a valid column name.
71                return None
72    
73      def read_record(self, index):      def field_range(self, fieldName):
74          return dict([(self.fields[i][0], self.data[index][i])          self.__deprecation_warning()
75                        for i in range(len(self.fields))])          min, max = self.ValueRange(fieldName)
76            return ((min, None), (max, None))
77    
78      def write_record(self, record, values):      def GetUniqueValues(self, field):
79          # TODO: Check for correct lenght and perhaps also          self.__deprecation_warning()
80          # for correct types in case values is a tuple. How to report problems?          return self.UniqueValues(field)
81          # TODO: Allow values to be a dictionary and write the single  
82          # fields that are specified.      def read_record(self, r):
83          self.data[record] = values          self.__deprecation_warning()
84            return self.ReadRowAsDict(r)
85    
86    
87  class DBFTable:  
88    class DBFColumn:
89    
90        """Description of a column in a DBFTable
91    
92        Instances have the following public attributes:
93    
94        name -- Name of the column
95        type -- Type of the column (one of FIELDTYPE_STRING, FIELDTYPE_INT or\
96                FIELDTYPE_DOUBLE)
97        index -- The index of the column
98        width -- the width of the data in the column
99        prec -- The precision of the data (only valid for type == FIELDTYPE_DOUBLE)
100        """
101    
102        def __init__(self, name, type, width, prec, index):
103            self.name = name
104            self.type = type
105            self.width = width
106            self.prec = prec
107            self.index = index
108    
109    
110    class DBFTable(OldTableInterfaceMixin):
111    
112      """      """
113      Table interface for the data in a DBF file      Table interface for the data in a DBF file
# Line 89  class DBFTable: Line 134  class DBFTable:
134          # If true, self.dbf is open for writing.          # If true, self.dbf is open for writing.
135          self._writable = 0          self._writable = 0
136    
137      def Destroy(self):          # Create the column information objects
138          self.dbf.close()          self.columns = []
139          self.dbf = None          self.column_map = {}
140            for i in range(self.NumColumns()):
141                ftype, name, width, prec = self.dbf.field_info(i)
142                ftype = dbflib_fieldtypes[ftype]
143                index = len(self.columns)
144                col = DBFColumn(name, ftype, width, prec, index)
145                self.columns.append(col)
146                self.column_map[name] = col
147                self.column_map[index] = col
148    
149      def record_count(self):      def NumRows(self):
150          """Return the number of records"""          """Return the number of rows in the table"""
151          return self.dbf.record_count()          return self.dbf.record_count()
152    
153      def field_count(self):      def NumColumns(self):
154          """Return the number of fields in a record"""          """Return the number of columns in the table"""
155          return self.dbf.field_count()          return self.dbf.field_count()
156    
157      def field_info(self, field):      def Columns(self):
158          """Return a tuple (type, name, width, prec) for the field no. field          """Return the table's colum definitions
159    
160          type is the data type of the field, name the name, width the          The return value is a sequence of DBFColumn instances, one for
161          field width in characters and prec the decimal precision.          each column.
162          """          """
163          type, name, width, prec = self.dbf.field_info(field)          return self.columns
         type = dbflib_fieldtypes[type]  
         return type, name, width, prec  
164    
165      def field_info_by_name(self, fieldName):      def Column(self, col):
166          count = self.field_count()          """Return information about the column given by its name or index
167    
168          for i in range(count):          The returned object is an instance of DBFColumn
169              info = self.field_info(i)          """
170              if info[1] == fieldName:          return self.column_map[col]
                 return info  
   
         return None  
   
     def field_range(self, fieldName):  
         """Finds the first occurences of the minimum and maximum values  
         in the table for the given field.  
171    
172          This assumes that the standard comparison operators (<, >, etc.)      def HasColumn(self, col):
173          will work for the given data.          """Return whether the table has a column with the given name or index
174            """
175            return self.column_map.has_key(col)
176    
177          Returns a tuple ((min, rec), (max, rec)) where:      def ReadRowAsDict(self, row):
178              min is the minimum value          """Return the entire row as a dictionary with column names as keys"""
179              max is the maximum value          return self.dbf.read_record(row)
             rec is the record number where the value was found. One  
                 should check that the record number of min is not  
                 the same as the record number of max.  
180    
181          Returns None if there are no records      def ReadValue(self, row, col):
182            """Return the value of the specified row and column
183    
184            The col parameter may be the index of the column or its name.
185          """          """
186            return self.dbf.read_record(row)[self.column_map[col].name]
187    
188        def ValueRange(self, col):
189            """Return the minimum and maximum values of the values in the column
190    
191          count = self.record_count()          The return value is a tuple (min, max) unless the table is empty
192            in which case the return value is None.
193            """
194            count = self.NumRows()
195    
196          if count == 0:          if count == 0:
197              return None              return None
198    
199          rec = self.read_record(0)          min = max = self.ReadValue(0, col)
   
         min = rec[fieldName]  
         min_rec = 0  
   
         max = rec[fieldName]  
         max_rec = 0  
   
200          for i in range(1, count):          for i in range(1, count):
201              rec = self.read_record(i)              value = self.ReadValue(i, col)
202              data = rec[fieldName]              if value < min:
203                    min = value
204                elif value > max:
205                    max = value
206    
207              if data < min:          return (min, max)
                 min = data  
                 min_rec = rec  
             elif data > max:  
                 max = data  
                 max_rec = rec  
   
         return ((min, min_rec), (max, max_rec))  
   
     def GetUniqueValues(self, fieldName):  
         """Return a list of all unique entries in the table for the given  
         field name.  
         """  
208    
209        def UniqueValues(self, col):
210            """Return a sorted list of all unique values in the column col"""
211          dict = {}          dict = {}
212    
213          for i in range(0, self.record_count()):          for i in range(self.NumRows()):
214              rec = self.read_record(i)              value = self.ReadValue(i, col)
215              data = rec[fieldName]              dict[value] = 0
216    
217              if not dict.has_key(data):          values = dict.keys()
218                  dict[data] = 0          values.sort()
219            return values
220    
         return dict.keys()  
221    
222      def read_record(self, record):      # DBF specific interface parts.
223          """Return the record no. record as a dict mapping field names to values  
224          """      def Destroy(self):
225          return self.dbf.read_record(record)          self.dbf.close()
226            self.dbf = None
227    
228      def write_record(self, record, values):      def write_record(self, record, values):
229          """Write the values into the record          """Write the values into the record
# Line 210  class DBFTable: Line 248  class DBFTable:
248    
249    
250    
251  # Temporary backwards compatibility  class MemoryColumn:
252  Table = DBFTable  
253        def __init__(self, name, type, index):
254            self.name = name
255            self.type = type
256            self.index = index
257    
258    class MemoryTable(OldTableInterfaceMixin):
259    
260        """Very simple table implementation that operates on a list of tuples"""
261    
262        def __init__(self, fields, data):
263            """Initialize the MemoryTable
264    
265            Parameters:
266            fields -- List of (name, field_type) pairs
267            data -- List of tuples, one for each row of data
268            """
269            self.data = data
270    
271            # Create the column information objects
272            self.columns = []
273            self.column_map = {}
274            for name, ftype in fields:
275                index = len(self.columns)
276                col = MemoryColumn(name, ftype, index)
277                self.columns.append(col)
278                self.column_map[name] = col
279                self.column_map[index] = col
280    
281        def NumColumns(self):
282            """Return the number of columns in the table"""
283            return len(self.columns)
284    
285        def Column(self, col):
286            """Return information about the column given by its name or index
287    
288            The returned object is an instance of MemoryColumn.
289            """
290            return self.column_map[col]
291    
292        def Columns(self):
293            """Return the table's colum definitions
294    
295            The return value is a sequence of MemoryColumn instances, one
296            for each column.
297            """
298            return self.columns
299    
300        def HasColumn(self, col):
301            """Return whether the table has a column with the given name or index
302            """
303            return self.column_map.has_key(col)
304    
305        def NumRows(self):
306            """Return the number of rows in the table"""
307            return len(self.data)
308    
309        def ReadValue(self, row, col):
310            """Return the value of the specified row and column
311    
312            The col parameter may be the index of the column or its name.
313            """
314            return self.data[row][self.column_map[col].index]
315    
316        def ReadRowAsDict(self, index):
317            """Return the entire row as a dictionary with column names as keys"""
318            return dict([(col.name, self.data[index][col.index])
319                          for col in self.columns])
320    
321        def ValueRange(self, col):
322            """Return the minimum and maximum values of the values in the column
323    
324            The return value is a tuple (min, max) unless the table is empty
325            in which case the return value is None.
326            """
327    
328            index = self.column_map[col].index
329            values = [row[index] for row in self.data]
330            if not values:
331                return None
332    
333            return min(values), max(values)
334    
335        def UniqueValues(self, col):
336            """Return a sorted list of all unique values in the column col"""
337            dict = {}
338    
339            for i in range(self.NumRows()):
340                value = self.ReadValue(i, col)
341                dict[value] = 0
342    
343            values = dict.keys()
344            values.sort()
345            return values
346    
347    
348        def write_record(self, record, values):
349            # TODO: Check for correct lenght and perhaps also
350            # for correct types in case values is a tuple. How to report problems?
351            # TODO: Allow values to be a dictionary and write the single
352            # fields that are specified.
353            self.data[record] = values

Legend:
Removed from v.806  
changed lines
  Added in v.907

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26