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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 765 - (hide annotations)
Tue Apr 29 12:42:14 2003 UTC (21 years, 10 months ago) by bh
Original Path: trunk/thuban/Thuban/Model/table.py
File MIME type: text/x-python
File size: 5169 byte(s)
Next step of table implementation. Introduce a transient database
using SQLite that some of the data is copied to on demand. This
allows us to do joins and other operations that require an index
for good performance with reasonable efficiency. Thuban now needs
SQLite 2.8.0 and pysqlite 0.4.1. Older versions may work but I
haven't tested that.

* Thuban/Model/transientdb.py: New. Transient database
implementation.

* test/test_transientdb.py: New. Tests for the transient DB
classes.

* Thuban/Model/session.py (AutoRemoveFile, AutoRemoveDir): New
classes to help automatically remove temporary files and
directories.
(Session.__init__): New instance variables temp_dir for the
temporary directory and transient_db for the SQLite database
(Session.temp_directory): New. Create a temporary directory if not
yet done and return its name. Use AutoRemoveDir to have it
automatically deleted
(Session.TransientDB): Instantiate the transient database if not
done yet and return it.

* Thuban/Model/data.py (ShapefileStore.__init__): Use an
AutoTransientTable so that data is copied to the transient DB on
demand.
(SimpleStore): New class that simply combines a table and a
shapefile

* Thuban/Model/table.py (Table, DBFTable): Rename Table into
DBFTable and update its doc-string to reflect the fact that this
is only the table interface to a DBF file. Table is now an alias
for DBFTable for temporary backwards compatibility.

* Thuban/UI/application.py (ThubanApplication.OnExit): Make sure
the last reference to the session goes away so that the temporary
files are removed properly.

* test/test_load.py (LoadSessionTest.tearDown): Remove the
reference to the session to make sure the temporary files are
removed.

1 bh 590 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 bh 6 # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8     """
9     Classes for handling tables of data.
10     """
11    
12     __version__ = "$Revision$"
13    
14     import dbflib
15    
16     # the field types supported by a Table instance.
17 jonathan 474 FIELDTYPE_INT = "int"
18     FIELDTYPE_STRING = "string"
19     FIELDTYPE_DOUBLE = "double"
20 bh 6
21    
22     # map the dbflib constants for the field types to our constants
23     dbflib_fieldtypes = {dbflib.FTString: FIELDTYPE_STRING,
24     dbflib.FTInteger: FIELDTYPE_INT,
25     dbflib.FTDouble: FIELDTYPE_DOUBLE}
26    
27 bh 765 class DBFTable:
28 bh 6
29     """
30 bh 765 Table interface for the data in a DBF file
31 bh 6 """
32    
33 bh 286 # Implementation strategy regarding writing to a DBF file:
34     #
35     # Most of the time Thuban only needs to read from a table and it is
36     # important that Thuban can work with read-only files. Therefore the
37     # DBF file is opened only for reading initially. Only when
38     # write_record is called we try to open the DBF file for writing as
39 bh 590 # well. If that succeeds the read/write DBF file will be used for
40     # all IO afterwards.
41 bh 286 #
42     # It's important to use the same DBF file object for both reading
43     # and writing to make sure that reading a records after writing
44     # returns the new values. With two separate objects this wouldn't
45     # work because a DBF file object buffers some data
46    
47 bh 6 def __init__(self, filename):
48     self.filename = filename
49 bh 284 self.dbf = dbflib.DBFFile(filename)
50 bh 6
51 bh 286 # If true, self.dbf is open for writing.
52     self._writable = 0
53    
54 bh 257 def Destroy(self):
55     self.dbf.close()
56     self.dbf = None
57    
58 bh 6 def record_count(self):
59     """Return the number of records"""
60     return self.dbf.record_count()
61    
62     def field_count(self):
63     """Return the number of fields in a record"""
64     return self.dbf.field_count()
65    
66     def field_info(self, field):
67     """Return a tuple (type, name, width, prec) for the field no. field
68    
69     type is the data type of the field, name the name, width the
70     field width in characters and prec the decimal precision.
71     """
72     type, name, width, prec = self.dbf.field_info(field)
73     type = dbflib_fieldtypes[type]
74     return type, name, width, prec
75    
76 jonathan 467 def field_info_by_name(self, fieldName):
77     count = self.field_count()
78    
79     for i in range(count):
80     info = self.field_info(i)
81     if info[1] == fieldName:
82     return info
83    
84     return None
85    
86 jonathan 628 def field_range(self, fieldName):
87     """Finds the first occurences of the minimum and maximum values
88     in the table for the given field.
89    
90     This assumes that the standard comparison operators (<, >, etc.)
91     will work for the given data.
92    
93     Returns a tuple ((min, rec), (max, rec)) where:
94     min is the minimum value
95     max is the maximum value
96     rec is the record number where the value was found. One
97     should check that the record number of min is not
98     the same as the record number of max.
99    
100     Returns None if there are no records
101    
102     """
103    
104    
105     count = self.record_count()
106    
107     if count == 0:
108     return None
109    
110     rec = self.read_record(0)
111    
112     min = rec[fieldName]
113     min_rec = 0
114    
115     max = rec[fieldName]
116     max_rec = 0
117    
118     for i in range(1, count):
119     rec = self.read_record(i)
120     data = rec[fieldName]
121    
122     if data < min:
123     min = data
124     min_rec = rec
125     elif data > max:
126     max = data
127     max_rec = rec
128    
129     return ((min, min_rec), (max, max_rec))
130    
131     def GetUniqueValues(self, fieldName):
132     """Return a list of all unique entries in the table for the given
133     field name.
134     """
135    
136     dict = {}
137    
138     for i in range(0, self.record_count()):
139     rec = self.read_record(i)
140     data = rec[fieldName]
141    
142     if not dict.has_key(data):
143     dict[data] = 0
144    
145     return dict.keys()
146    
147 bh 6 def read_record(self, record):
148     """Return the record no. record as a dict mapping field names to values
149     """
150     return self.dbf.read_record(record)
151    
152 bh 274 def write_record(self, record, values):
153     """Write the values into the record
154    
155     The values parameter may either be a dictionary or a sequence.
156    
157     If it's a dictionary the keys must be the names of the fields
158     and their value must have a suitable type. Only the fields
159     actually contained in the dictionary are written. Fields for
160     which there's no item in the dict are not modified.
161    
162     If it's a sequence, all fields must be present in the right
163     order.
164     """
165 bh 286 if not self._writable:
166     new_dbf = dbflib.DBFFile(self.filename, "r+b")
167     self.dbf.close()
168     self.dbf = new_dbf
169     self._writable = 1
170     self.dbf.write_record(record, values)
171     self.dbf.commit()
172 jonathan 467
173 bh 765
174    
175     # Temporary backwards compatibility
176     Table = DBFTable

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26