/[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 1278 - (show annotations)
Fri Jun 20 17:46:58 2003 UTC (21 years, 8 months ago) by jonathan
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 16285 byte(s)
Add tests in each type of layer for HasClassification() and HasShapes()

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.color import Color
31 from Thuban.Model.table import FIELDTYPE_DOUBLE, FIELDTYPE_STRING, MemoryTable
32 from Thuban.Model.proj import Projection
33 from Thuban.Model.data import DerivedShapeStore
34 from Thuban.Model.classification import Classification, ClassGroupSingleton
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(field = "CLPTLABEL")
245 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
246 self.layer.SetClassification(self.classification)
247 self.layer.UnsetModified()
248 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
249 self.subscribe_with_params,
250 LAYER_SHAPESTORE_REPLACED)
251 self.layer.Subscribe(LAYER_CHANGED,
252 self.subscribe_with_params, LAYER_CHANGED)
253
254 def tearDown(self):
255 self.clear_messages()
256 self.layer.Destroy()
257 self.session.Destroy()
258 self.session = self.layer = self.store = self.classification = None
259
260 def test_sanity(self):
261 """SetShapeStoreTests sanity check
262
263 Test the initial state of the test case instances after setUp.
264 """
265 cls = self.layer.GetClassification()
266 self.assert_(cls is self.classification)
267 self.assertEquals(cls.GetField(), "CLPTLABEL")
268 self.assertEquals(cls.GetFieldType(), FIELDTYPE_STRING)
269 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
270 self.failIf(self.layer.WasModified())
271
272 def test_set_shape_store_modified_flag(self):
273 """Test whether Layer.SetShapeStore() sets the modified flag"""
274 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
275 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
276 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
277
278 self.assert_(self.layer.WasModified())
279
280 def test_set_shape_store_different_field_name(self):
281 """Test Layer.SetShapeStore() with different column name"""
282 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
283 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
284 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
285 # The classification should contain only the default group now.
286 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
287 self.check_messages([(self.layer, LAYER_CHANGED),
288 (self.layer, LAYER_SHAPESTORE_REPLACED)])
289
290 def test_set_shape_store_same_field(self):
291 """Test Layer.SetShapeStore() with same column name and type"""
292 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
293 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
294 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
295 # The classification should be the same as before
296 self.assert_(self.layer.GetClassification() is self.classification)
297 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
298
299 def test_set_shape_store_same_field_different_type(self):
300 """Test Layer.SetShapeStore() with same column name but different type
301 """
302 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
303 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
304 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
305 # The classification should contain only the default group now.
306 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
307 self.check_messages([(self.layer, LAYER_CHANGED),
308 (self.layer, LAYER_SHAPESTORE_REPLACED)])
309
310
311 class TestLayerLegend(unittest.TestCase, support.SubscriberMixin):
312
313 """Test cases for Layer method that modify the layer.
314 """
315
316 def setUp(self):
317 """Clear the list of received messages and create a layer and a session
318
319 The layer is bound to self.layer and the session to self.session.
320 """
321 self.clear_messages()
322 self.session = Session("Test session for %s" % self.__class__)
323 filename = os.path.join("..", "Data", "iceland", "political.shp")
324 self.layer = Layer("Test Layer",
325 self.session.OpenShapefile(filename))
326 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
327 LAYER_LEGEND_CHANGED)
328 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
329 self.subscribe_with_params,
330 LAYER_VISIBILITY_CHANGED)
331
332 def tearDown(self):
333 """Clear the list of received messages and explictly destroy self.layer
334 """
335 self.layer.Destroy()
336 self.layer = None
337 self.session.Destroy()
338 self.session = None
339 self.clear_messages()
340
341 def test_initial_settings(self):
342 """Test Layer's initial legend attributes"""
343 # test default settings
344 self.failIf(self.layer.WasModified())
345 #self.assertEquals(self.layer.fill, None)
346 #self.assertEquals(self.layer.stroke.hex(), "#000000")
347 #self.assertEquals(self.layer.stroke_width, 1)
348 self.assertEquals(self.layer.Visible(), 1)
349 # no messages should have been produced
350 self.check_messages([])
351
352 def test_visibility(self):
353 """Test Layer visibility"""
354 self.layer.SetVisible(0)
355 self.assertEquals(self.layer.Visible(), 0)
356 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
357
358 # currently, modifying the visibility doesn't count as changing
359 # the layer.
360 self.failIf(self.layer.WasModified())
361
362
363 #
364 # the tree info now contains Color objects which are difficult to test
365 #
366 # def test_tree_info(self):
367 # """Test Layer.TreeInfo"""
368 # self.assertEquals(self.layer.TreeInfo(),
369 # ("Layer 'Test Layer'",
370 # ['Shown',
371 # 'Shapes: 156',
372 # ('Extent (lat-lon):'
373 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
374 # 'Shapetype: Polygon',
375 # 'Fill: None',
376 # 'Outline: (0.000, 0.000, 0.000)']))
377
378
379 if __name__ == "__main__":
380 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