/[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 1262 - (show annotations)
Fri Jun 20 14:15:30 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: 15877 byte(s)
(TestLayer.test_derived_store): Add
        a test for the new exception in DerivedShapeStore.__init__.

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.assertEquals(layer.GetProjection(), None)
81
82 # set/get projection
83 proj = Projection(["proj=utm", "zone=26"])
84
85 layer.SetProjection(proj)
86 self.failUnless(layer.GetProjection() is proj)
87
88 # __init__ with other arguments
89 layer = BaseLayer("Test BaseLayer", False, proj)
90 self.failIf(layer.Visible())
91 self.failUnless(layer.GetProjection() is proj)
92
93 def test_arc_layer(self):
94 """Test Layer with arc shapes"""
95 layer = self.layer = Layer("Test Layer",
96 self.open_shapefile("roads-line.shp"))
97 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
98 self.assertEquals(layer.NumShapes(), 839)
99 shape = layer.Shape(32)
100 self.assertFloatTuplesEqual(shape.Points(),
101 [(-15.082174301147461, 66.27738189697265),
102 (-15.026350021362305, 66.27339172363281)])
103 self.assertFloatSeqEqual(layer.BoundingBox(),
104 [-24.450359344482422, 63.426830291748047,
105 -13.55668830871582, 66.520111083984375])
106 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25)),
107 [613, 726, 838])
108
109 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
110 [-15.082174301147461, 66.27339172363281,
111 -15.026350021362305, 66.27738189697265])
112
113 shape = layer.Shape(33)
114 self.assertFloatTuplesEqual(shape.Points(),
115 [(-22.248506546020508, 66.30645751953125),
116 (-22.232730865478516, 66.294075012207031),
117 (-22.23158073425293, 66.287689208984375),
118 (-22.246318817138672, 66.270065307617188)])
119
120 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]),
121 [-22.248506546020508, 66.270065307617188,
122 -15.026350021362305, 66.30645751953125])
123
124 self.assertEquals(layer.ShapesBoundingBox([]), None)
125 self.assertEquals(layer.ShapesBoundingBox(None), None)
126
127 def test_polygon_layer(self):
128 """Test Layer with polygon shapes"""
129 layer = self.layer = Layer("Test Layer",
130 self.open_shapefile("political.shp"))
131 self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
132 self.assertEquals(layer.NumShapes(), 156)
133 shape = layer.Shape(4)
134 self.assertFloatTuplesEqual(shape.Points(),
135 [(-22.406391143798828, 64.714111328125),
136 (-22.41621208190918, 64.71600341796875),
137 (-22.406051635742188, 64.719200134277344),
138 (-22.406391143798828, 64.714111328125)])
139 self.assertFloatSeqEqual(layer.BoundingBox(),
140 [-24.546524047851562, 63.286754608154297,
141 -13.495815277099609, 66.563774108886719])
142 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1)),
143 [91, 92, 144, 146, 148, 150, 152, 153])
144
145 def test_point_layer(self):
146 """Test Layer with point shapes"""
147 layer = self.layer = Layer("Test Layer",
148 self.open_shapefile("cultural_landmark-point.shp"))
149 self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
150 self.assertEquals(layer.NumShapes(), 34)
151 shape = layer.Shape(0)
152 self.assertFloatTuplesEqual(shape.Points(),
153 [(-22.711074829101562, 66.36572265625)])
154 self.assertFloatSeqEqual(layer.BoundingBox(),
155 [-23.806047439575195, 63.405960083007812,
156 -15.12291431427002, 66.36572265625])
157 self.assertEquals(layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1)),
158 [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
159
160 def test_empty_layer(self):
161 """Test Layer with empty shape file"""
162 # create an empty shape file
163 shapefilename = self.temp_file_name("layer_empty.shp")
164 shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
165 shp.close()
166 # create an empty DBF file too because Thuban can't cope yet
167 # with missing DBF file.
168 dbffilename = self.temp_file_name("layer_empty.dbf")
169 dbf = dbflib.create(dbffilename)
170 dbf.add_field("NAME", dbflib.FTString, 20, 0)
171
172 # Now try to open it.
173 layer = self.layer = Layer("Empty Layer",
174 self.session.OpenShapefile(shapefilename))
175 self.assertEquals(layer.BoundingBox(), None)
176 self.assertEquals(layer.LatLongBoundingBox(), None)
177 self.assertEquals(layer.NumShapes(), 0)
178
179 def test_get_field_type(self):
180 """Test Layer.GetFieldType()"""
181 layer = self.layer = Layer("Test Layer",
182 self.open_shapefile("roads-line.shp"))
183 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
184 self.assertEquals(layer.GetFieldType("non existing"), None)
185
186 def test_raster_layer(self):
187 if not Thuban.Model.resource.has_gdal_support():
188 return
189
190 filename = self.build_path("island.tif")
191 layer = RasterLayer("Test RasterLayer", filename)
192 self.assertEquals(layer.GetImageFilename(), filename)
193 self.assertFloatSeqEqual(layer.BoundingBox(),
194 [-24.5500000, 63.2833330,
195 -13.4916670, 66.5666670])
196 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
197 [-24.5500000, 63.2833330,
198 -13.4916670, 66.5666670])
199
200 def test_derived_store(self):
201 """Test layer with derived store"""
202 layer = self.layer = Layer("Test Layer",
203 self.open_shapefile("roads-line.shp"))
204 try:
205 store = layer.ShapeStore()
206 derived = DerivedShapeStore(store, store.Table())
207 layer.SetShapeStore(derived)
208 self.assert_(layer.ShapeStore() is derived)
209
210 # check that an exception is raised when the number
211 # of shapes differ from the number of rows in a table.
212 layer2 = Layer("Test Layer",
213 self.open_shapefile("political.shp"))
214 store2 = layer2.ShapeStore()
215 self.assertRaises(ValueError,
216 DerivedShapeStore, store2, store.Table())
217
218 finally:
219 store = derived = None
220 layer2.Destroy()
221 store2 = None
222
223
224 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
225
226 def setUp(self):
227 """Create a layer with a classification as self.layer"""
228 self.clear_messages()
229 self.session = Session("Test session for %s" % self.__class__)
230 self.shapefilename = os.path.join("..", "Data", "iceland",
231 "cultural_landmark-point.dbf")
232 self.store = self.session.OpenShapefile(self.shapefilename)
233 self.layer = Layer("test layer", self.store)
234 self.classification = Classification(field = "CLPTLABEL")
235 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
236 self.layer.SetClassification(self.classification)
237 self.layer.UnsetModified()
238 self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
239 self.subscribe_with_params,
240 LAYER_SHAPESTORE_REPLACED)
241 self.layer.Subscribe(LAYER_CHANGED,
242 self.subscribe_with_params, LAYER_CHANGED)
243
244 def tearDown(self):
245 self.clear_messages()
246 self.layer.Destroy()
247 self.session.Destroy()
248 self.session = self.layer = self.store = self.classification = None
249
250 def test_sanity(self):
251 """SetShapeStoreTests sanity check
252
253 Test the initial state of the test case instances after setUp.
254 """
255 cls = self.layer.GetClassification()
256 self.assert_(cls is self.classification)
257 self.assertEquals(cls.GetField(), "CLPTLABEL")
258 self.assertEquals(cls.GetFieldType(), FIELDTYPE_STRING)
259 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
260 self.failIf(self.layer.WasModified())
261
262 def test_set_shape_store_modified_flag(self):
263 """Test whether Layer.SetShapeStore() sets the modified flag"""
264 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
265 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
266 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
267
268 self.assert_(self.layer.WasModified())
269
270 def test_set_shape_store_different_field_name(self):
271 """Test Layer.SetShapeStore() with different column name"""
272 memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
273 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
274 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
275 # The classification should contain only the default group now.
276 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
277 self.check_messages([(self.layer, LAYER_CHANGED),
278 (self.layer, LAYER_SHAPESTORE_REPLACED)])
279
280 def test_set_shape_store_same_field(self):
281 """Test Layer.SetShapeStore() with same column name and type"""
282 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
283 [("bla",)] * self.layer.ShapeStore().Table().NumRows())
284 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
285 # The classification should be the same as before
286 self.assert_(self.layer.GetClassification() is self.classification)
287 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
288
289 def test_set_shape_store_same_field_different_type(self):
290 """Test Layer.SetShapeStore() with same column name but different type
291 """
292 memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
293 [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
294 self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
295 # The classification should contain only the default group now.
296 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
297 self.check_messages([(self.layer, LAYER_CHANGED),
298 (self.layer, LAYER_SHAPESTORE_REPLACED)])
299
300
301 class TestLayerLegend(unittest.TestCase, support.SubscriberMixin):
302
303 """Test cases for Layer method that modify the layer.
304 """
305
306 def setUp(self):
307 """Clear the list of received messages and create a layer and a session
308
309 The layer is bound to self.layer and the session to self.session.
310 """
311 self.clear_messages()
312 self.session = Session("Test session for %s" % self.__class__)
313 filename = os.path.join("..", "Data", "iceland", "political.shp")
314 self.layer = Layer("Test Layer",
315 self.session.OpenShapefile(filename))
316 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
317 LAYER_LEGEND_CHANGED)
318 self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
319 self.subscribe_with_params,
320 LAYER_VISIBILITY_CHANGED)
321
322 def tearDown(self):
323 """Clear the list of received messages and explictly destroy self.layer
324 """
325 self.layer.Destroy()
326 self.layer = None
327 self.session.Destroy()
328 self.session = None
329 self.clear_messages()
330
331 def test_initial_settings(self):
332 """Test Layer's initial legend attributes"""
333 # test default settings
334 self.failIf(self.layer.WasModified())
335 #self.assertEquals(self.layer.fill, None)
336 #self.assertEquals(self.layer.stroke.hex(), "#000000")
337 #self.assertEquals(self.layer.stroke_width, 1)
338 self.assertEquals(self.layer.Visible(), 1)
339 # no messages should have been produced
340 self.check_messages([])
341
342 def test_visibility(self):
343 """Test Layer visibility"""
344 self.layer.SetVisible(0)
345 self.assertEquals(self.layer.Visible(), 0)
346 self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
347
348 # currently, modifying the visibility doesn't count as changing
349 # the layer.
350 self.failIf(self.layer.WasModified())
351
352
353 #
354 # the tree info now contains Color objects which are difficult to test
355 #
356 # def test_tree_info(self):
357 # """Test Layer.TreeInfo"""
358 # self.assertEquals(self.layer.TreeInfo(),
359 # ("Layer 'Test Layer'",
360 # ['Shown',
361 # 'Shapes: 156',
362 # ('Extent (lat-lon):'
363 # ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
364 # 'Shapetype: Polygon',
365 # 'Fill: None',
366 # 'Outline: (0.000, 0.000, 0.000)']))
367
368
369 if __name__ == "__main__":
370 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