/[thuban]/branches/WIP-pyshapelib-bramz/test/test_layer.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/test/test_layer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1452 - (show annotations)
Fri Jul 18 12:57:59 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 17107 byte(s)
* Thuban/Model/layer.py (Layer.__init__): Rename
classificationField to classificatin_column and init it here so
that it can be used in SetClassificationColumn
(Layer.GetClassificationColumn, Layer.GetClassificationField):
Rename to GetClassificationColumn.
(Layer.SetClassificationColumn, Layer.SetClassificationField):
Rename to SetClassificationColumn and issue a LAYER_CHANGED
message if the column changes.
(Layer._classification_changed, Layer.ClassChanged): Rename to
_classification_changed. Update the callers.
(Layer.SetShapeStore): Further field->column renames.

* Thuban/Model/load.py (SessionLoader.start_classification)
(SessionLoader.start_clpoint): Updates because of
field->column method name changes in the Layer class

* Thuban/Model/save.py (SessionSaver.write_classification): Updates
because of field->column method name changes in the Layer class

* Thuban/UI/classifier.py (Classifier.__init__)
(Classifier._OnTry, Classifier._OnRevert): Updates because of
field->column method name changes in the Layer class

* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Updates
because of field->column method name changes in the Layer class

* Thuban/UI/viewport.py (ViewPort.find_shape_at): Updates because
of field->column method name changes in the Layer class

* test/test_save.py (SaveSessionTest.testClassifiedLayer)
(SaveSessionTest.testClassifiedLayer): Update because of
field->column method name changes in the Layer class

* test/test_layer.py (SetShapeStoreTests.setUp)
(SetShapeStoreTests.test_sanity): Update because of field->column
method name changes in the Layer class
(TestLayerModification.setUp): Subscribe to LAYER_CHANGED as well
(TestLayerModification.test_sanity)
(TestLayerModification.test_initial_settings): remove unsued code
and rename to test_sanity.
(TestLayerModification.test_set_classification): New test for
SetClassification and SetClassificationField.

1 # Copyright (c) 2002, 2003 by Intevation GmbH
2 # 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 Test the Layer class
10 """
11
12 __version__ = "$Revision$"
13 # $Source$
14 # $Id$
15
16 import os
17 import unittest
18
19 import support
20 support.initthuban()
21
22 import shapelib
23 import dbflib
24
25 from Thuban.Model.session import Session
26 from Thuban.Model.layer import BaseLayer, Layer, RasterLayer, \
27 SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
28 from Thuban.Model.messages import LAYER_LEGEND_CHANGED, \
29 LAYER_VISIBILITY_CHANGED, LAYER_SHAPESTORE_REPLACED, LAYER_CHANGED
30 from Thuban.Model.table import FIELDTYPE_DOUBLE, FIELDTYPE_STRING, MemoryTable
31 from Thuban.Model.proj import Projection
32 from Thuban.Model.data import DerivedShapeStore
33 from Thuban.Model.classification import Classification, ClassGroupSingleton, \
34 ClassGroupRange
35
36 import Thuban.Model.resource
37
38 class TestLayer(unittest.TestCase, support.FileTestMixin,
39 support.FloatComparisonMixin):
40
41 """Test cases for different layer (shape) types"""
42
43 def assertFloatTuplesEqual(self, test, value):
44 """Assert equality of two lists of tuples of float"""
45 for i in range(len(test)):
46 self.assertFloatSeqEqual(test[i], value[i])
47
48 def setUp(self):
49 """Create a session self.session and initialize self.layer to None"""
50 self.session = Session("Test session for %s" % self.__class__)
51 self.layer = None
52
53 def tearDown(self):
54 """Call the layer's Destroy method and set session and layer to None"""
55 self.session = None
56 if self.layer is not None:
57 self.layer.Destroy()
58 self.layer = None
59
60 def build_path(self, filename):
61 return os.path.join("..", "Data", "iceland", filename)
62
63 def open_shapefile(self, filename):
64 """Open and return a shapestore for filename in the iceland data set"""
65 return self.session.OpenShapefile(self.build_path(filename))
66
67 def test_base_layer(self):
68 layer = self.layer = BaseLayer("Test BaseLayer")
69 self.assertEquals(layer.Title(), "Test BaseLayer")
70 self.failUnless(layer.Visible())
71
72 # toggle visibility
73 layer.SetVisible(False)
74 self.failIf(layer.Visible())
75
76 layer.SetVisible(True)
77 self.failUnless(layer.Visible())
78
79 self.failIf(layer.HasClassification())
80 self.failIf(layer.HasShapes())
81
82 self.assertEquals(layer.GetProjection(), None)
83
84 # set/get projection
85 proj = Projection(["proj=utm", "zone=26"])
86
87 layer.SetProjection(proj)
88 self.failUnless(layer.GetProjection() is proj)
89
90 # __init__ with other arguments
91 layer = BaseLayer("Test BaseLayer", False, proj)
92 self.failIf(layer.Visible())
93 self.failUnless(layer.GetProjection() is proj)
94
95 def test_arc_layer(self):
96 """Test Layer with arc shapes"""
97 layer = self.layer = Layer("Test Layer",
98 self.open_shapefile("roads-line.shp"))
99 self.failUnless(layer.HasClassification())
100 self.failUnless(layer.HasShapes())
101 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
102 self.assertEquals(layer.NumShapes(), 839)
103 shape = layer.Shape(32)
104 self.assertFloatTuplesEqual(shape.Points(),
105 [(-15.082174301147461, 66.27738189697265),
106 (-15.026350021362305, 66.27339172363281)])
107 self.assertFloatSeqEqual(layer.BoundingBox(),
108 [-24.450359344482422, 63.426830291748047,
109 -13.55668830871582, 66.520111083984375])
110 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25)),
111 [613, 726, 838])
112
113 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
114 [-15.082174301147461, 66.27339172363281,
115 -15.026350021362305, 66.27738189697265])
116
117 shape = layer.Shape(33)
118 self.assertFloatTuplesEqual(shape.Points(),
119 [(-22.248506546020508, 66.30645751953125),
120 (-22.232730865478516, 66.294075012207031),
121 (-22.23158073425293, 66.287689208984375),
122 (-22.246318817138672, 66.270065307617188)])
123
124 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]),
125 [-22.248506546020508, 66.270065307617188,
126 -15.026350021362305, 66.30645751953125])
127
128 self.assertEquals(layer.ShapesBoundingBox([]), None)
129 self.assertEquals(layer.ShapesBoundingBox(None), None)
130
131 def test_polygon_layer(self):
132 """Test Layer with polygon shapes"""
133 layer = self.layer = Layer("Test Layer",
134 self.open_shapefile("political.shp"))
135 self.failUnless(layer.HasClassification())
136 self.failUnless(layer.HasShapes())
137 self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
138 self.assertEquals(layer.NumShapes(), 156)
139 shape = layer.Shape(4)
140 self.assertFloatTuplesEqual(shape.Points(),
141 [(-22.406391143798828, 64.714111328125),
142 (-22.41621208190918, 64.71600341796875),
143 (-22.406051635742188, 64.719200134277344),
144 (-22.406391143798828, 64.714111328125)])
145 self.assertFloatSeqEqual(layer.BoundingBox(),
146 [-24.546524047851562, 63.286754608154297,
147 -13.495815277099609, 66.563774108886719])
148 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1)),
149 [91, 92, 144, 146, 148, 150, 152, 153])
150
151 def test_point_layer(self):
152 """Test Layer with point shapes"""
153 layer = self.layer = Layer("Test Layer",
154 self.open_shapefile("cultural_landmark-point.shp"))
155 self.failUnless(layer.HasClassification())
156 self.failUnless(layer.HasShapes())
157 self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
158 self.assertEquals(layer.NumShapes(), 34)
159 shape = layer.Shape(0)
160 self.assertFloatTuplesEqual(shape.Points(),
161 [(-22.711074829101562, 66.36572265625)])
162 self.assertFloatSeqEqual(layer.BoundingBox(),
163 [-23.806047439575195, 63.405960083007812,
164 -15.12291431427002, 66.36572265625])
165 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1)),
166 [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
167
168 def test_empty_layer(self):
169 """Test Layer with empty shape file"""
170 # create an empty shape file
171 shapefilename = self.temp_file_name("layer_empty.shp")
172 shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
173 shp.close()
174 # create an empty DBF file too because Thuban can't cope yet
175 # with missing DBF file.
176 dbffilename = self.temp_file_name("layer_empty.dbf")
177 dbf = dbflib.create(dbffilename)
178 dbf.add_field("NAME", dbflib.FTString, 20, 0)
179
180 # Now try to open it.
181 layer = self.layer = Layer("Empty Layer",
182 self.session.OpenShapefile(shapefilename))
183 self.assertEquals(layer.BoundingBox(), None)
184 self.assertEquals(layer.LatLongBoundingBox(), None)
185 self.assertEquals(layer.NumShapes(), 0)
186
187 def test_get_field_type(self):
188 """Test Layer.GetFieldType()"""
189 layer = self.layer = Layer("Test Layer",
190 self.open_shapefile("roads-line.shp"))
191 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
192 self.assertEquals(layer.GetFieldType("non existing"), None)
193
194 def test_raster_layer(self):
195 if not Thuban.Model.resource.has_gdal_support():
196 return
197
198 filename = self.build_path("island.tif")
199 layer = RasterLayer("Test RasterLayer", filename)
200 self.failIf(layer.HasClassification())
201 self.failIf(layer.HasShapes())
202 self.assertEquals(layer.GetImageFilename(), filename)
203 self.assertFloatSeqEqual(layer.BoundingBox(),
204 [-24.5500000, 63.2833330,
205 -13.4916670, 66.5666670])
206 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
207 [-24.5500000, 63.2833330,
208 -13.4916670, 66.5666670])
209
210 def test_derived_store(self):
211 """Test layer with derived store"""
212 layer = self.layer = Layer("Test Layer",
213 self.open_shapefile("roads-line.shp"))
214 try:
215 store = layer.ShapeStore()
216 derived = DerivedShapeStore(store, store.Table())
217 layer.SetShapeStore(derived)
218 self.assert_(layer.ShapeStore() is derived)
219
220 # check that an exception is raised when the number
221 # of shapes differ from the number of rows in a table.
222 layer2 = Layer("Test Layer",
223 self.open_shapefile("political.shp"))
224 store2 = layer2.ShapeStore()
225 self.assertRaises(ValueError,
226 DerivedShapeStore, store2, store.Table())
227
228 finally:
229 store = derived = None
230 layer2.Destroy()
231 store2 = None
232
233
234 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
235
236 def setUp(self):
237 """Create a layer with a classification as self.layer"""
238 self.clear_messages()
239 self.session = Session("Test session for %s" % self.__class__)
240 self.shapefilename = os.path.join("..", "Data", "iceland",
241 "cultural_landmark-point.dbf")
242 self.store = self.session.OpenShapefile(self.shapefilename)
243 self.layer = Layer("test layer", self.store)
244 self.classification = Classification()
245 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
246 self.layer.SetClassificationColumn("CLPTLABEL")
247 self.layer.SetClassification(self.classification)
248 self.layer.UnsetModified()
249 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
250 self.subscribe_with_params,
251 LAYER_SHAPESTORE_REPLACED)
252 self.layer.Subscribe(LAYER_CHANGED,
253 self.subscribe_with_params, LAYER_CHANGED)
254
255 def tearDown(self):
256 self.clear_messages()
257 self.layer.Destroy()
258 self.session.Destroy()
259 self.session = self.layer = self.store = self.classification = None
260
261 def test_sanity(self):
262 """SetShapeStoreTests sanity check
263
264 Test the initial state of the test case instances after setUp.
265 """
266 cls = self.layer.GetClassification()
267 self.assert_(cls is self.classification)
268 field = self.layer.GetClassificationColumn()
269 self.assertEquals(field, "CLPTLABEL")
270 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
271 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
272 self.failIf(self.layer.WasModified())
273
274 def test_set_shape_store_modified_flag(self):
275 """Test whether Layer.SetShapeStore() sets the modified flag"""
276 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
277 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
278 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
279
280 self.assert_(self.layer.WasModified())
281
282 def test_set_shape_store_different_field_name(self):
283 """Test Layer.SetShapeStore() with different column name"""
284 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
285 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
286 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
287 # The classification should contain only the default group now.
288 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
289 self.check_messages([(self.layer, LAYER_CHANGED),
290 (self.layer, LAYER_SHAPESTORE_REPLACED)])
291
292 def test_set_shape_store_same_field(self):
293 """Test Layer.SetShapeStore() with same column name and type"""
294 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
295 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
296 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
297 # The classification should be the same as before
298 self.assert_(self.layer.GetClassification() is self.classification)
299 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
300
301 def test_set_shape_store_same_field_different_type(self):
302 """Test Layer.SetShapeStore() with same column name but different type
303 """
304 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
305 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
306 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
307 # The classification should contain only the default group now.
308 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
309 self.check_messages([(self.layer, LAYER_CHANGED),
310 (self.layer, LAYER_SHAPESTORE_REPLACED)])
311
312
313 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
314
315 """Test cases for Layer method that modify the layer.
316 """
317
318 def setUp(self):
319 """Clear the list of received messages and create a layer and a session
320
321 The layer is bound to self.layer and the session to self.session.
322 """
323 self.clear_messages()
324 self.session = Session("Test session for %s" % self.__class__)
325 filename = os.path.join("..", "Data", "iceland", "political.shp")
326 self.layer = Layer("Test Layer",
327 self.session.OpenShapefile(filename))
328 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
329 LAYER_LEGEND_CHANGED)
330 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
331 self.subscribe_with_params,
332 LAYER_VISIBILITY_CHANGED)
333 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
334 LAYER_CHANGED)
335
336 def tearDown(self):
337 """Clear the list of received messages and explictly destroy self.layer
338 """
339 self.layer.Destroy()
340 self.layer = None
341 self.session.Destroy()
342 self.session = None
343 self.clear_messages()
344
345 def test_sanity(self):
346 """TestLayerModification Sanity Checks"""
347 # test default settings
348 self.failIf(self.layer.WasModified())
349 self.assertEquals(self.layer.Visible(), 1)
350 # no messages should have been produced
351 self.check_messages([])
352
353 def test_visibility(self):
354 """Test Layer visibility"""
355 self.layer.SetVisible(0)
356 self.assertEquals(self.layer.Visible(), 0)
357 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
358
359 # currently, modifying the visibility doesn't count as changing
360 # the layer.
361 self.failIf(self.layer.WasModified())
362
363 def test_set_classification(self):
364 """Test Layer.SetClassification"""
365 classification = Classification()
366 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
367
368 self.layer.SetClassification(classification)
369 self.layer.SetClassificationColumn("AREA")
370
371 self.check_messages([(self.layer, LAYER_CHANGED),
372 (self.layer, LAYER_CHANGED)])
373 self.failUnless(self.layer.WasModified())
374
375 self.clear_messages()
376 self.layer.UnsetModified()
377
378 # change only the classification column. This should issue a
379 # LAYER_CHANGED message as well.
380 self.layer.SetClassificationColumn("PERIMETER")
381
382 self.check_messages([(self.layer, LAYER_CHANGED)])
383 self.failUnless(self.layer.WasModified())
384
385
386 #
387 # the tree info now contains Color objects which are difficult to test
388 #
389 # def test_tree_info(self):
390 # """Test Layer.TreeInfo"""
391 # self.assertEquals(self.layer.TreeInfo(),
392 # ("Layer 'Test Layer'",
393 # ['Shown',
394 # 'Shapes: 156',
395 # ('Extent (lat-lon):'
396 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
397 # 'Shapetype: Polygon',
398 # 'Fill: None',
399 # 'Outline: (0.000, 0.000, 0.000)']))
400
401
402 if __name__ == "__main__":
403 support.run_tests()

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26