/[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 1687 - (show annotations)
Fri Aug 29 10:02:16 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: 23977 byte(s)
Add some missing parameters to projections. Proj complains about
them on windows but for some reason not on Linux.

* test/test_save.py (SaveSessionTest.testLayerProjection): Add
missing required projection parameters

* test/test_proj.py (TestProjFile.test): Add missing required
projection parameters

* test/test_load_0_8.py (TestLayerProjection.file_contents)
(TestLayerProjection.test): Add missing required projection
parameters and tests for them

* test/test_load.py (TestLayerProjection.file_contents)
(TestLayerProjection.test): Add missing required projection
parameters and tests for them

* test/test_layer.py (TestLayer.test_base_layer): Add missing
required projection parameters

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