/[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 1142 - (show annotations)
Tue Jun 10 09:41:57 2003 UTC (21 years, 9 months ago) by bh
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 15320 byte(s)
* Thuban/Model/messages.py (LAYER_SHAPESTORE_REPLACED): New
message.

* Thuban/Model/layer.py (Layer.SetShapeStore): Send
LAYER_SHAPESTORE_REPLACED when the shapestore changes. A
LAYER_CHANGED will still be sent if the classification changes.

* Thuban/UI/classifier.py (Classifier.__init__): Add the map as
parameter so we can subscribe to some of its messages
(Classifier.__init__): Subscribe to the map's MAP_LAYERS_REMOVED
and the layer's LAYER_SHAPESTORE_REPLACED
(Classifier.unsubscribe_messages): New. Unsubscribe from message
subscribed to in __init__
(Classifier.map_layers_removed)
(Classifier.layer_shapestore_replaced): receivers for the messages
subscribed to in __init__. Unsubscribe and close the dialog

* Thuban/UI/mainwindow.py (MainWindow.OpenLayerProperties): Pass
the map to the Classifier dialog

* test/test_layer.py (SetShapeStoreTests): Derive from
SubscriberMixin as well so we can test messages
(SetShapeStoreTests.setUp): Subscribe to some of the layer's
messages
(SetShapeStoreTests.tearDown): Clear the messages again
(SetShapeStoreTests.test_sanity): Expand the doc-string and check
for the modified flag too
(SetShapeStoreTests.test_set_shape_store_modified_flag): New test
to check whether SetShapeStore sets the modified flag
(SetShapeStoreTests.test_set_shape_store_different_field_name)
(SetShapeStoreTests.test_set_shape_store_same_field)
(SetShapeStoreTests.test_set_shape_store_same_field_different_type):
Add tests for the messages. This checks both the new
LAYER_SHAPESTORE_REPLACED and the older LAYER_CHANGED

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