/[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 1025 by frank, Mon May 26 11:46:17 2003 UTC revision 1389 by jonathan, Thu Jul 10 14:53:27 2003 UTC
# Line 133  class DBFTable(TitledObject, OldTableInt Line 133  class DBFTable(TitledObject, OldTableInt
133    
134      def __init__(self, filename):      def __init__(self, filename):
135          self.filename = filename          self.filename = filename
136          title = os.path.basename(self.filename)  
137            # Omit the extension in the title as it's not really needed and
138            # it can be confusing because dbflib removes extensions and
139            # appends some variations of '.dbf' before it tries to open the
140            # file. So the title could be e.g. myshapefile.shp when the real
141            # filename is myshapefile.dbf
142            title = os.path.splitext(os.path.basename(self.filename))[0]
143          TitledObject.__init__(self, title)          TitledObject.__init__(self, title)
144    
145          self.dbf = dbflib.DBFFile(filename)          self.dbf = dbflib.DBFFile(filename)
146    
147          # If true, self.dbf is open for writing.          # If true, self.dbf is open for writing.
# Line 230  class DBFTable(TitledObject, OldTableInt Line 237  class DBFTable(TitledObject, OldTableInt
237    
238      # DBF specific interface parts.      # DBF specific interface parts.
239    
     def Precision(self, col):  
         """Return column precision"""  
         return self.column_map[col].prec  
   
240      def Width(self, col):      def Width(self, col):
241          """Return column width"""          """Return column width"""
242          return self.column_map[col].width          return self.column_map[col].width
# Line 372  class MemoryTable(TitledObject, OldTable Line 375  class MemoryTable(TitledObject, OldTable
375      def Width(self, col):      def Width(self, col):
376          """Return the maximum width of values in the column          """Return the maximum width of values in the column
377    
378          The return value is the the maximum length of string representation          The return value is the the maximum length of string
379          of the values in the column (represented by index or name)."""          representation of the values in the column (represented by index
380            or name).
381            """
382          max = 0          max = 0
383            
384          type  = self.column_map[col].type          type  = self.column_map[col].type
385          index = self.column_map[col].index          index = self.column_map[col].index
386          values = [row[index] for row in self.data]          values = [row[index] for row in self.data]
# Line 383  class MemoryTable(TitledObject, OldTable Line 388  class MemoryTable(TitledObject, OldTable
388              return None              return None
389    
390          if type == FIELDTYPE_DOUBLE:          if type == FIELDTYPE_DOUBLE:
391              prec = self.Precision(col)              format = "%.12f"
             format = "%%.%df" % prec  
392          elif type == FIELDTYPE_INT:          elif type == FIELDTYPE_INT:
393              format = "%d"              format = "%d"
394          else:          else:
# Line 396  class MemoryTable(TitledObject, OldTable Line 400  class MemoryTable(TitledObject, OldTable
400    
401          return max          return max
402    
     def Precision(self, col):  
         """Return the precision of the column  
   
         The return value is the maximum number of numeric characters after the  
         decimal if column type is double. Else precision zero is returned.  
         The column can be represented by index or name.  
         """  
       
         type  = self.column_map[col].type  
         if type == FIELDTYPE_DOUBLE:  
             index = self.column_map[col].index  
             values = [row[index] for row in self.data]  
             if not values:  
                 return 0  
               
             max = 0  
             for value in values:  
                 l = len(str(value % 1))  
                 if l > max:  
                     max = l  
             if max > 2:  
                 return max - 2  
             else:  
                 return 0  
         else:  
             return 0  
             
403      def Dependencies(self):      def Dependencies(self):
404          """Return an empty sequence. The MemoryTable doesn't depend on anything          """Return an empty sequence. The MemoryTable doesn't depend on anything
405          """          """
# Line 436  class MemoryTable(TitledObject, OldTable Line 413  class MemoryTable(TitledObject, OldTable
413          self.data[record] = values          self.data[record] = values
414    
415    
416  def table_to_dbf(table, filename):  
417    def _find_dbf_column_names(names):
418        """Determine the column names to use in a DBF file
419    
420        DBF files have a length limit of 10 characters on the column names
421        so when writing an arbitrary Thuban table to a DBF file we may have
422        we may have to rename some of the columns making sure that they're
423        unique in the DBF file too.
424    
425        Names that are already short enough will stay the same. Longer names
426        will be truncated to 10 characters or if that isn't unique it will
427        be truncated more and filled up with digits.
428    
429        The parameter names should be a list of the column names. The return
430        value will be a dictionary mapping the names in the input list to
431        the names to use in the DBF file.
432        """
433        # mapping from the original names in table to the names in the DBF
434        # file
435        name_map = {}
436    
437        # First, we keep all names that are already short enough
438        for i in range(len(names) - 1, -1, -1):
439            if len(names[i]) <= 10:
440                name_map[names[i]] = names[i]
441                del names[i]
442    
443        # dict used as a set of all names already used as DBF column names
444        used = name_map.copy()
445    
446        # Go through all longer names. If the name truncated to 10
447        # characters is not used already, we use that. Otherwise we truncate
448        # it more and append numbers until we get an unused name
449        for name in names:
450            truncated = name[:10]
451            num = 0; numstr = ""
452            #print "truncated", truncated, num
453            while truncated in used and len(numstr) < 10:
454                num += 1
455                numstr = str(num)
456                truncated = name[:10 - len(numstr)] + numstr
457                #print "truncated", truncated, num
458            if len(numstr) >= 10:
459                # This case should never happen in practice as tables with
460                # 10^10 columns seem very unlikely :)
461                raise ValueError("Can't find unique dbf column name")
462    
463            name_map[name] = truncated
464            used[truncated] = 1
465    
466        return name_map
467    
468    def table_to_dbf(table, filename, records = None):
469      """Create the dbf file filename from the table"""      """Create the dbf file filename from the table"""
470      dbf = dbflib.create(filename)      dbf = dbflib.create(filename)
471    
# Line 444  def table_to_dbf(table, filename): Line 473  def table_to_dbf(table, filename):
473                           FIELDTYPE_INT: dbflib.FTInteger,                           FIELDTYPE_INT: dbflib.FTInteger,
474                           FIELDTYPE_DOUBLE: dbflib.FTDouble}                           FIELDTYPE_DOUBLE: dbflib.FTDouble}
475    
476    
477        name_map = _find_dbf_column_names([col.name for col in table.Columns()])
478    
479      # Initialise the header. Distinguish between DBFTable and others.      # Initialise the header. Distinguish between DBFTable and others.
480      for col in table.Columns():      for col in table.Columns():
         prec  = table.Precision(col.name)  
481          width = table.Width(col.name)          width = table.Width(col.name)
482          dbf.add_field(col.name, dbflib_fieldtypes[col.type], width, prec)          if col.type == FIELDTYPE_DOUBLE:
483                prec = getattr(col, "prec", 12)
484      for i in range(table.NumRows()):          else:
485          record = table.ReadRowAsDict(i)              prec = 0
486          dbf.write_record(i, record)          dbf.add_field(name_map[col.name], dbflib_fieldtypes[col.type],
487                          width, prec)
488    
489        if records is None:
490            records = range(table.NumRows())
491    
492        recNum = 0
493        for i in records:
494            record = {}
495            for key, value in table.ReadRowAsDict(i).items():
496                record[name_map[key]] = value
497            dbf.write_record(recNum, record)
498            recNum += 1
499      dbf.close()      dbf.close()
500    
501  def table_to_csv(table, filename):  def table_to_csv(table, filename, records = None):
502      """Export table to csv file."""      """Export table to csv file."""
503    
504      file = open(filename,"w")      file = open(filename,"w")
# Line 467  def table_to_csv(table, filename): Line 510  def table_to_csv(table, filename):
510          header = header + "\n"          header = header + "\n"
511          file.write(header)          file.write(header)
512    
513          for i in range(table.NumRows()):          if records is None:
514                records = range(table.NumRows())
515    
516            for i in records:
517              record = table.ReadRowAsDict(i)              record = table.ReadRowAsDict(i)
518              if len(record):              if len(record):
519                  line = "%s" % record[columns[0].name]                  line = "%s" % record[columns[0].name]

Legend:
Removed from v.1025  
changed lines
  Added in v.1389

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26