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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1599 - (show annotations)
Mon Aug 18 12:45:28 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/test/test_save.py
File MIME type: text/x-python
File size: 21244 byte(s)
Fix some bugs in Thuban and the test suite that were uncovered by
changes introduced in Python 2.3:

* Thuban/Model/table.py (DBFTable.__init__): Make sure the
filename is an absolute name

* Thuban/Model/layer.py (RasterLayer.__init__): Make sure the
filename is an absolute name

* test/test_save.py (SaveSessionTest.testRasterLayer): Use a
unique filename to save to and use the correct relative filename
in the expected output.
(SaveSessionTest.test_dbf_table): Use the correct relative
filename in the expected output.

* test/test_layer.py (TestLayer.test_raster_layer): Update the
test to check whether the filename is absolute.

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 saving a thuban session as XML
10 """
11
12 __version__ = "$Revision$"
13 # $Source$
14 # $Id$
15
16 import os
17 import unittest
18 from StringIO import StringIO
19
20 import xml.sax
21 import xml.sax.handler
22 from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
23
24 import xmlsupport
25
26 import support
27 support.initthuban()
28
29 import dbflib
30
31 from Thuban.Lib.fileutil import relative_filename
32 from Thuban.Model.save import XMLWriter, save_session, sort_data_stores
33 from Thuban.Model.session import Session
34 from Thuban.Model.map import Map
35 from Thuban.Model.layer import Layer, RasterLayer
36 from Thuban.Model.proj import Projection
37 from Thuban.Model.table import DBFTable
38 from Thuban.Model.transientdb import TransientJoinedTable
39 from Thuban.Model.data import DerivedShapeStore
40
41 from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
42 ClassGroupProperties
43
44 from Thuban.Model.range import Range
45
46
47 class XMLWriterTest(unittest.TestCase):
48
49 def testEncode(self):
50 """Test XMLWriter.encode"""
51 writer = XMLWriter()
52 eq = self.assertEquals
53
54 eq(writer.encode("hello world"), "hello world")
55 eq(writer.encode(unicode("hello world")), unicode("hello world"))
56
57 eq(writer.encode("\x80\x90\xc2\x100"),
58 "\xc2\x80\xc2\x90\xc3\x82\x100")
59 eq(writer.encode(u"\x80\x90\xc2\x100"),
60 "\xc2\x80\xc2\x90\xc3\x82\x100")
61 eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
62
63 eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
64 eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
65
66 class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
67 xmlsupport.ValidationTest):
68
69 dtd = "http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd"
70 thubanids = [((dtd, n), (None, "id")) for n in
71 ["fileshapesource", "filetable", "jointable",
72 "derivedshapesource"]]
73 thubanidrefs = [((dtd, n), (None, m)) for n, m in
74 [("layer", "shapestore"),
75 ("jointable", "left"),
76 ("jointable", "right"),
77 ("derivedshapesource", "table"),
78 ("derivedshapesource", "shapesource")]]
79 del n, m, dtd
80
81 def compare_xml(self, xml1, xml2):
82 list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
83 idrefs = self.thubanidrefs)
84 list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
85 idrefs = self.thubanidrefs)
86 if list1 != list2:
87 for a, b in zip(list1, list2):
88 if a != b:
89 self.fail("%r != %r" % (a, b))
90
91
92 def testEmptySession(self):
93 """Save an empty session"""
94 session = Session("empty session")
95 filename = self.temp_file_name("save_emptysession.thuban")
96 save_session(session, filename)
97 session.Destroy()
98
99 file = open(filename)
100 written_contents = file.read()
101 file.close()
102 self.compare_xml(written_contents,
103 '<?xml version="1.0" encoding="UTF-8"?>\n'
104 '<!DOCTYPE session SYSTEM "thuban-0.9.dtd">\n'
105 '<session title="empty session" '
106 'xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">'
107 '\n</session>\n')
108
109 self.validate_data(written_contents)
110
111 def testSingleLayer(self):
112 """Save a session with a single map with a single layer"""
113 # deliberately put an apersand in the title :)
114 session = Session("single map&layer")
115 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
116 map = Map("Test Map", projection = proj)
117 session.AddMap(map)
118 # use shapefile from the example data
119 shpfile = os.path.join(os.path.dirname(__file__),
120 os.pardir, "Data", "iceland", "political.shp")
121 layer = Layer("My Layer", session.OpenShapefile(shpfile))
122 map.AddLayer(layer)
123
124 filename = self.temp_file_name("save_singlemap.thuban")
125 save_session(session, filename)
126
127 file = open(filename)
128 written_contents = file.read()
129 file.close()
130 expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
131 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
132 <session title="single map&amp;layer"
133 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
134 <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
135 <map title="Test Map">
136 <projection name="Unknown">
137 <parameter value="zone=26"/>
138 <parameter value="proj=utm"/>
139 <parameter value="ellps=clrk66"/>
140 </projection>
141 <layer title="My Layer" shapestore="D1"
142 fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
143 </map>
144 </session>'''
145
146 expected_contents = expected_template % \
147 (os.path.join("..", "..", "Data", "iceland", "political.shp"),
148 "true")
149
150 self.compare_xml(written_contents, expected_contents)
151
152 self.validate_data(written_contents)
153
154 layer.SetVisible(False)
155 save_session(session, filename)
156
157 file = open(filename)
158 written_contents = file.read()
159 file.close()
160 expected_contents = expected_template % \
161 (os.path.join("..", "..", "Data", "iceland", "political.shp"),
162 "false")
163 self.compare_xml(written_contents, expected_contents)
164 self.validate_data(written_contents)
165
166 session.Destroy()
167
168 def testLayerProjection(self):
169 """Test saving layers with projections"""
170 # deliberately put an apersand in the title :)
171 session = Session("single map&layer")
172 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
173 map = Map("Test Map", projection = proj)
174 session.AddMap(map)
175 # use shapefile from the example data
176 shpfile = os.path.join(os.path.dirname(__file__),
177 os.pardir, "Data", "iceland", "political.shp")
178 layer = Layer("My Layer", session.OpenShapefile(shpfile))
179 proj = Projection(["proj=lcc", "ellps=clrk66"], "Layer Projection")
180 layer.SetProjection(proj)
181 map.AddLayer(layer)
182
183 filename = self.temp_file_name("save_layerproj.thuban")
184 save_session(session, filename)
185 session.Destroy()
186
187 file = open(filename)
188 written_contents = file.read()
189 file.close()
190 expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
191 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
192 <session title="single map&amp;layer"
193 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
194 <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
195 <map title="Test Map">
196 <projection name="Unknown">
197 <parameter value="zone=26"/>
198 <parameter value="proj=utm"/>
199 <parameter value="ellps=clrk66"/>
200 </projection>
201 <layer title="My Layer" shapestore="D1"
202 fill="None" stroke="#000000" stroke_width="1" visible="true">
203 <projection name="Layer Projection">
204 <parameter value="proj=lcc"/>
205 <parameter value="ellps=clrk66"/>
206 </projection>
207 </layer>
208 </map>
209 </session>''' % os.path.join("..", "..", "Data", "iceland",
210 "political.shp")
211 #print written_contents
212 #print "********************************************"
213 #print expected_contents
214 self.compare_xml(written_contents, expected_contents)
215
216 self.validate_data(written_contents)
217
218 def testRasterLayer(self):
219 # deliberately put an apersand in the title :)
220 session = Session("single map&layer")
221 map = Map("Test Map")
222 session.AddMap(map)
223 # use shapefile from the example data
224 imgfile = os.path.join(os.path.dirname(__file__),
225 os.pardir, "Data", "iceland", "island.tif")
226 layer = RasterLayer("My RasterLayer", imgfile)
227 map.AddLayer(layer)
228
229 filename = self.temp_file_name("%s.thuban" % self.id())
230 save_session(session, filename)
231 session.Destroy()
232
233 file = open(filename)
234 written_contents = file.read()
235 file.close()
236 expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
237 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
238 <session title="single map&amp;layer"
239 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
240 <map title="Test Map">
241 <rasterlayer title="My RasterLayer" filename="%s"
242 visible="true">
243 </rasterlayer>
244 </map>
245 </session>''' % os.path.join(os.pardir, os.pardir, "Data", "iceland",
246 "island.tif")
247 #print written_contents
248 #print "********************************************"
249 #print expected_contents
250 self.compare_xml(written_contents, expected_contents)
251
252 self.validate_data(written_contents)
253
254 def testClassifiedLayer(self):
255 """Save a session with a single map with classifications"""
256 # deliberately put an apersand in the title :)
257 session = Session("Map with Classifications")
258 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
259 map = Map("Test Map", projection = proj)
260 session.AddMap(map)
261 # use shapefile from the example data
262 shpfile = os.path.join(os.path.dirname(__file__),
263 os.pardir, "Data", "iceland", "political.shp")
264 layer = Layer("My Layer", session.OpenShapefile(shpfile))
265 map.AddLayer(layer)
266 layer2 = Layer("My Layer", layer.ShapeStore())
267 map.AddLayer(layer2)
268
269 clazz = layer.GetClassification()
270
271 layer.SetClassificationColumn("AREA")
272
273 clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
274 "single"))
275 clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
276 "single-text"))
277
278 clazz.AppendGroup(ClassGroupRange((0, 42),
279 ClassGroupProperties(),
280 "range"))
281
282 range = ClassGroupRange(Range("[0;42]"))
283 range.SetProperties(ClassGroupProperties())
284 range.SetLabel("new-range")
285 clazz.AppendGroup(range)
286
287
288 clazz = layer2.GetClassification()
289 layer2.SetClassificationColumn("POPYCOUN")
290
291 # Classification with Latin 1 text
292 clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
293 ClassGroupProperties(),
294 '\xdcml\xe4uts')) # Uemlaeuts
295
296
297 filename = self.temp_file_name("%s.thuban" % self.id())
298 save_session(session, filename)
299
300 file = open(filename)
301 written_contents = file.read()
302 file.close()
303 expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
304 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
305 <session title="Map with Classifications"
306 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
307 <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
308 <map title="Test Map">
309 <projection name="Unknown">
310 <parameter value="zone=26"/>
311 <parameter value="proj=utm"/>
312 <parameter value="ellps=clrk66"/>
313 </projection>
314 <layer title="My Layer" shapestore="D1"
315 fill="None" stroke="#000000" stroke_width="1" visible="%s">
316 <classification field="AREA" field_type="double">
317 <clnull label="">
318 <cldata fill="None" stroke="#000000" stroke_width="1"/>
319 </clnull>
320 <clpoint value="42" label="single">
321 <cldata fill="None" stroke="#000000" stroke_width="1"/>
322 </clpoint>
323 <clpoint value="text" label="single-text">
324 <cldata fill="None" stroke="#000000" stroke_width="1"/>
325 </clpoint>
326 <clrange range="[0;42[" label="range">
327 <cldata fill="None" stroke="#000000" stroke_width="1"/>
328 </clrange>
329 <clrange range="[0;42]" label="new-range">
330 <cldata fill="None" stroke="#000000" stroke_width="1"/>
331 </clrange>
332 </classification>
333 </layer>
334 <layer title="My Layer" shapestore="D1"
335 fill="None" stroke="#000000" stroke_width="1" visible="true">
336 <classification field="POPYCOUN" field_type="string">
337 <clnull label="">
338 <cldata fill="None" stroke="#000000" stroke_width="1"/>
339 </clnull>
340 <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
341 label="\xc3\x9cml\xc3\xa4uts">
342 <cldata fill="None" stroke="#000000" stroke_width="1"/>
343 </clpoint>
344 </classification>
345 </layer>
346 </map>
347 </session>'''
348
349 expected_contents = expected_template % \
350 (os.path.join("..", "..", "Data", "iceland", "political.shp"),
351 "true")
352
353 #print written_contents
354 #print "********************************************"
355 #print expected_contents
356 self.compare_xml(written_contents, expected_contents)
357
358 self.validate_data(written_contents)
359
360 session.Destroy()
361
362 def test_dbf_table(self):
363 """Test saving a session with a dbf table link"""
364 session = Session("a DBF Table session")
365 # use shapefile from the example data
366 dbffile = os.path.join(os.path.dirname(__file__),
367 os.pardir, "Data", "iceland", "political.dbf")
368 table = session.AddTable(DBFTable(dbffile))
369
370 filename = self.temp_file_name("save_singletable.thuban")
371 save_session(session, filename)
372
373 file = open(filename)
374 written_contents = file.read()
375 file.close()
376 expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
377 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
378 <session title="a DBF Table session"
379 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
380 <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
381 </session>'''
382
383 expected_contents = (expected_template
384 % os.path.join(os.pardir, os.pardir, "Data",
385 "iceland", "political.dbf"))
386 self.compare_xml(written_contents, expected_contents)
387
388 def test_joined_table(self):
389 """Test saving a session with joined table"""
390 # Create a simple table to use in the join
391 dbffile = self.temp_file_name("save_joinedtable.dbf")
392 dbf = dbflib.create(dbffile)
393 dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
394 dbf.add_field("TEXT", dbflib.FTString, 10, 0)
395 dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
396 dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
397 dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
398 dbf.close()
399
400 # Create the session and a map
401 session = Session("A Joined Table session")
402 try:
403 map = Map("Test Map")
404 session.AddMap(map)
405
406 # Add the dbf file to the session
407 dbftable = session.AddTable(DBFTable(dbffile))
408
409 # Create a layer with the shapefile to use in the join
410 shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
411 os.pardir, "Data", "iceland",
412 "roads-line.shp")
413 layer = Layer("My Layer", session.OpenShapefile(shpfile))
414 map.AddLayer(layer)
415
416 # Do the join
417 store = layer.ShapeStore()
418 #for col in store.Table().Columns():
419 # print col.name
420 joined = TransientJoinedTable(session.TransientDB(),
421 store.Table(), "RDLNTYPE",
422 dbftable, "RDTYPE",
423 outer_join = True)
424 store = session.AddShapeStore(DerivedShapeStore(store, joined))
425 layer.SetShapeStore(store)
426
427 # Save the session
428 filename = self.temp_file_name("save_joinedtable.thuban")
429 save_session(session, filename)
430
431 # Read it back and compare
432 file = open(filename)
433 written_contents = file.read()
434 file.close()
435 expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
436 <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
437 <session title="A Joined Table session"
438 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
439 <fileshapesource filename="%(shpfile)s"
440 filetype="shapefile" id="D142197204"/>
441 <filetable filename="%(dbffile)s"
442 title="save_joinedtable"
443 filetype="DBF" id="D141881756"/>
444 <jointable id="D142180284"
445 title="Join of roads-line and save_joinedtable"
446 leftcolumn="RDLNTYPE" left="D142197204"
447 rightcolumn="RDTYPE" right="D141881756"
448 jointype="LEFT OUTER" />
449 <derivedshapesource id="D141915644"
450 table="D142180284"
451 shapesource="D142197204"/>
452 <map title="Test Map">
453 <layer title="My Layer"
454 shapestore="D141915644" visible="true"
455 stroke="#000000" stroke_width="1" fill="None"/>
456 </map>
457 </session>'''
458
459 expected_contents = expected_template % {
460 "dbffile": relative_filename(self.temp_dir(), dbffile),
461 "shpfile": relative_filename(self.temp_dir(), shpfile)
462 }
463 self.compare_xml(written_contents, expected_contents)
464 finally:
465 session.Destroy()
466 session = None
467
468
469 class MockDataStore:
470
471 """A very simple data store that only has dependencies"""
472
473 def __init__(self, name, *dependencies):
474 self.name = name
475 self.dependencies = dependencies
476
477 def __repr__(self):
478 return self.name
479
480 def Dependencies(self):
481 return self.dependencies
482
483
484 class TestStoreSort(unittest.TestCase):
485
486 def check_sort(self, containers, sorted):
487 """Check whether the list of data containers is sorted"""
488 # check whether sorted is in the right order
489 seen = {}
490 for container in sorted:
491 self.failIf(id(container) in seen,
492 "Container %r at least twice in %r" % (container,
493 sorted))
494 for dep in container.Dependencies():
495 self.assert_(id(dep) in seen,
496 "Dependency %r of %r not yet seen" % (dep,
497 container))
498 seen[id(container)] = 1
499 # check whether all of containers is in sorted
500 for container in containers:
501 self.assert_(id(container) in seen,
502 "Container %r in containers but not in sorted")
503 self.assertEquals(len(containers), len(sorted))
504
505 def test_sort_data_stores(self):
506 """Test Thuban.Model.save.sort_data_stores"""
507 d1 = MockDataStore("d1")
508 d2 = MockDataStore("d2")
509 d3 = MockDataStore("d3", d1)
510 d4 = MockDataStore("d4", d1, d3)
511
512 containers = [d4, d1, d2, d3]
513 self.check_sort(containers, sort_data_stores(containers))
514 containers = [d1, d3, d2, d4]
515 self.check_sort(containers, sort_data_stores(containers))
516
517
518
519 if __name__ == "__main__":
520 # Fake the __file__ global because it's needed by a test
521 import sys
522 __file__ = sys.argv[0]
523 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