/[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 1538 - (show annotations)
Fri Aug 1 14:27:46 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: 17673 byte(s)
Import the SHAPETYPE_* constants from data
instead of layer.
(TestLayer.test_derived_store): Remove the test for the exception
when instantiating the DerivedShapeStore with an incompatible
table which is now in test_derivedshapestore.py. Add some more
tests of the layer methods to determine whether they work for a
DerivedShapeStore as well.

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 from Thuban.Model.data import 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 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
221 self.assertEquals(layer.NumShapes(), 839)
222 shape = layer.Shape(32)
223 self.assertFloatTuplesEqual(shape.Points(),
224 [(-15.082174301147461, 66.27738189697265),
225 (-15.026350021362305, 66.27339172363281)])
226 self.assertFloatSeqEqual(layer.BoundingBox(),
227 [-24.450359344482422, 63.426830291748047,
228 -13.55668830871582, 66.520111083984375])
229 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0,
230 -23.75, 64.25)),
231 [613, 726, 838])
232
233 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
234 [-15.082174301147461, 66.27339172363281,
235 -15.026350021362305, 66.27738189697265])
236
237 finally:
238 store = derived = None
239
240
241 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
242
243 def setUp(self):
244 """Create a layer with a classification as self.layer"""
245 self.clear_messages()
246 self.session = Session("Test session for %s" % self.__class__)
247 self.shapefilename = os.path.join("..", "Data", "iceland",
248 "cultural_landmark-point.dbf")
249 self.store = self.session.OpenShapefile(self.shapefilename)
250 self.layer = Layer("test layer", self.store)
251 self.classification = Classification()
252 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
253 self.layer.SetClassificationColumn("CLPTLABEL")
254 self.layer.SetClassification(self.classification)
255 self.layer.UnsetModified()
256 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
257 self.subscribe_with_params,
258 LAYER_SHAPESTORE_REPLACED)
259 self.layer.Subscribe(LAYER_CHANGED,
260 self.subscribe_with_params, LAYER_CHANGED)
261
262 def tearDown(self):
263 self.clear_messages()
264 self.layer.Destroy()
265 self.session.Destroy()
266 self.session = self.layer = self.store = self.classification = None
267
268 def test_sanity(self):
269 """SetShapeStoreTests sanity check
270
271 Test the initial state of the test case instances after setUp.
272 """
273 cls = self.layer.GetClassification()
274 self.assert_(cls is self.classification)
275 field = self.layer.GetClassificationColumn()
276 self.assertEquals(field, "CLPTLABEL")
277 self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
278 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
279 self.failIf(self.layer.WasModified())
280
281 def test_set_shape_store_modified_flag(self):
282 """Test whether Layer.SetShapeStore() sets the modified flag"""
283 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
284 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
285 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
286
287 self.assert_(self.layer.WasModified())
288
289 def test_set_shape_store_different_field_name(self):
290 """Test Layer.SetShapeStore() with different column name"""
291 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
292 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
293 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
294 # The classification should contain only the default group now.
295 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
296 self.check_messages([(self.layer, LAYER_CHANGED),
297 (self.layer, LAYER_SHAPESTORE_REPLACED)])
298
299 def test_set_shape_store_same_field(self):
300 """Test Layer.SetShapeStore() with same column name and type"""
301 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
302 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
303 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
304 # The classification should be the same as before
305 self.assert_(self.layer.GetClassification() is self.classification)
306 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
307
308 def test_set_shape_store_same_field_different_type(self):
309 """Test Layer.SetShapeStore() with same column name but different type
310 """
311 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
312 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
313 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
314 # The classification should contain only the default group now.
315 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
316 self.check_messages([(self.layer, LAYER_CHANGED),
317 (self.layer, LAYER_SHAPESTORE_REPLACED)])
318
319
320 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
321
322 """Test cases for Layer method that modify the layer.
323 """
324
325 def setUp(self):
326 """Clear the list of received messages and create a layer and a session
327
328 The layer is bound to self.layer and the session to self.session.
329 """
330 self.clear_messages()
331 self.session = Session("Test session for %s" % self.__class__)
332 filename = os.path.join("..", "Data", "iceland", "political.shp")
333 self.layer = Layer("Test Layer",
334 self.session.OpenShapefile(filename))
335 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
336 LAYER_LEGEND_CHANGED)
337 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
338 self.subscribe_with_params,
339 LAYER_VISIBILITY_CHANGED)
340 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
341 LAYER_CHANGED)
342
343 def tearDown(self):
344 """Clear the list of received messages and explictly destroy self.layer
345 """
346 self.layer.Destroy()
347 self.layer = None
348 self.session.Destroy()
349 self.session = None
350 self.clear_messages()
351
352 def test_sanity(self):
353 """TestLayerModification Sanity Checks"""
354 # test default settings
355 self.failIf(self.layer.WasModified())
356 self.assertEquals(self.layer.Visible(), 1)
357 # no messages should have been produced
358 self.check_messages([])
359
360 def test_visibility(self):
361 """Test Layer visibility"""
362 self.layer.SetVisible(0)
363 self.assertEquals(self.layer.Visible(), 0)
364 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
365
366 # currently, modifying the visibility doesn't count as changing
367 # the layer.
368 self.failIf(self.layer.WasModified())
369
370 def test_set_classification(self):
371 """Test Layer.SetClassification"""
372 classification = Classification()
373 classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
374
375 self.layer.SetClassification(classification)
376 self.layer.SetClassificationColumn("AREA")
377
378 self.check_messages([(self.layer, LAYER_CHANGED),
379 (self.layer, LAYER_CHANGED)])
380 self.failUnless(self.layer.WasModified())
381
382 self.clear_messages()
383 self.layer.UnsetModified()
384
385 # change only the classification column. This should issue a
386 # LAYER_CHANGED message as well.
387 self.layer.SetClassificationColumn("PERIMETER")
388
389 self.check_messages([(self.layer, LAYER_CHANGED)])
390 self.failUnless(self.layer.WasModified())
391
392
393 #
394 # the tree info now contains Color objects which are difficult to test
395 #
396 # def test_tree_info(self):
397 # """Test Layer.TreeInfo"""
398 # self.assertEquals(self.layer.TreeInfo(),
399 # ("Layer 'Test Layer'",
400 # ['Shown',
401 # 'Shapes: 156',
402 # ('Extent (lat-lon):'
403 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
404 # 'Shapetype: Polygon',
405 # 'Fill: None',
406 # 'Outline: (0.000, 0.000, 0.000)']))
407
408
409 if __name__ == "__main__":
410 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