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

Annotation of /branches/WIP-pyshapelib-bramz/test/test_load.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2551 - (hide annotations)
Thu Jan 27 14:19:41 2005 UTC (20 years, 1 month ago) by jonathan
Original Path: trunk/thuban/test/test_load.py
File MIME type: text/x-python
File size: 43002 byte(s)
Add a new dialog box for raster layers. The dialog box allows
the user to toggle a mask that is generated by ProjectRasterFile
and is used to only draw the real parts of the projected image.

1 bh 2104 # Copyright (c) 2002, 2003, 2004 by Intevation GmbH
2 bh 292 # 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 loading a thuban session from a file
10 bh 1247
11     The tests in this file (test_load.py) are always be the tests for the
12     current version of the thuban file format. Tests for older versions can
13     be found in the version specific test modules, e.g. test_load_0_2 for
14     files created by Thuban 0.2.
15    
16     Maintenance of the test cases:
17    
18     When during a development period the file format is changed with respect
19 bh 2104 to the last released version for the first time, the tests here should
20     be copied to the version specific test file. The round-trip tests which
21 bh 1257 save the session again and compare the XML files should not be copied
22     over as they only make sense here to make sure th that the files checked
23     here are actually ones that may have been written by the current thuban
24     version.
25 bh 292 """
26    
27     __version__ = "$Revision$"
28     # $Source$
29     # $Id$
30    
31     import os
32     import unittest
33    
34     import support
35     support.initthuban()
36    
37 bh 1646 import postgissupport
38 bh 1257 from xmlsupport import sax_eventlist
39 bh 1268
40     import dbflib
41 bh 1970 import shapelib
42 bh 1268
43 bh 1257 from Thuban.Model.save import save_session
44 bh 1646 from Thuban.Model.load import load_session, parse_color, LoadError, \
45     LoadCancelled
46 jonathan 1350 from Thuban.Model.color import Transparent
47 jonathan 684 from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
48     ClassGroupSingleton, ClassGroupDefault
49 bh 1646 from Thuban.Model.postgisdb import ConnectionError
50 bh 1970 from Thuban.Model.table import DBFTable, MemoryTable, \
51     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
52     table_to_dbf
53 bh 2034 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
54     ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
55 jonathan 684
56 bh 292 def filenames_equal(name1, name2):
57     """Return true if the filenames name1 and name2 are equal.
58    
59     On systems where it is available, simply use os.path.samefile,
60     otherwise return whether the normalized versions of the filenames
61     according to os.path.normpath are equal.
62     """
63     if hasattr(os.path, "samefile"):
64     return os.path.samefile(name1, name2)
65     return os.path.normpath(name1) == os.path.normpath(name2)
66    
67    
68 bh 957
69     class LoadSessionTest(support.FileLoadTestCase):
70    
71     """Base class for .thuban file loading tests
72    
73     Basically the same as the FileLoadTestCase, except that all tests
74     use the '.thuban' extension by default and that setUp and tearDown
75     handle sessions.
76     """
77    
78     file_extension = ".thuban"
79    
80     def setUp(self):
81     """Create the test files"""
82     support.FileLoadTestCase.setUp(self)
83     self.session = None
84    
85     def tearDown(self):
86     if self.session is not None:
87     self.session.Destroy()
88     self.session = None
89    
90 bh 1268
91 bh 2104 dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
92 bh 1268 thubanids = [((dtd, n), (None, "id")) for n in
93     ["fileshapesource", "filetable", "jointable",
94     "derivedshapesource"]]
95     thubanidrefs = [((dtd, n), (None, m)) for n, m in
96     [("layer", "shapestore"),
97     ("jointable", "left"),
98     ("jointable", "right"),
99     ("derivedshapesource", "table"),
100     ("derivedshapesource", "shapesource")]]
101 bh 1989
102     # The filenames in the tests should be understandable on all
103     # currently supported platforms so filenames is an empty list
104     filenames = []
105    
106 bh 1268 del n, m, dtd
107    
108 bh 1257 def check_format(self):
109     """Check whether the file we loaded from matches the one that
110     would be written. Call this from each test case after loading
111     the session
112     """
113     filename = self.temp_file_name(self.id() + ".roundtrip.thuban")
114     save_session(self.session, filename)
115 bh 1268 el1 = sax_eventlist(filename = filename, ids = self.thubanids,
116 bh 1683 idrefs = self.thubanidrefs,
117     filenames = self.filenames)
118 bh 1268 el2 = sax_eventlist(filename = self.filename(), ids = self.thubanids,
119 bh 1683 idrefs = self.thubanidrefs,
120     filenames = self.filenames)
121 bh 1268 if 0:
122     for a, b in zip(el1, el2):
123     print a != b and "***************" or ""
124     print a
125     print b
126 jonathan 2551
127 bh 1268 self.assertEquals(el1, el2,
128     "loaded file not equivalent to the saved file")
129 bh 957
130 bh 1257
131 bh 957 class ClassificationTest(LoadSessionTest):
132    
133     """
134     Base class for tests that do some detailed checking of classifications
135     """
136    
137     def TestLayers(self, layers, expected):
138     TITLE = 0
139     NUM_GROUPS = 1
140     CLASSES = 2
141     GROUP_TYPE = 0
142     GROUP_DATA = 1
143     GROUP_LABEL = 2
144     GROUP_PROPS = 3
145    
146     eq = self.assertEquals
147    
148     eq(len(layers), len(expected))
149    
150     for layer, data in zip(layers, expected):
151     eq(layer.Title(), data[TITLE])
152    
153     clazz = layer.GetClassification()
154     eq(clazz.GetNumGroups(), data[NUM_GROUPS])
155     eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
156    
157     i = 0
158     for group in clazz:
159     props = ClassGroupProperties()
160     props.SetLineColor(
161     parse_color(data[CLASSES][i][GROUP_PROPS][0]))
162     props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
163     props.SetFill(
164     parse_color(data[CLASSES][i][GROUP_PROPS][2]))
165 jan 2373 if len(data[CLASSES][i][GROUP_PROPS]) > 3:
166     props.SetSize(data[CLASSES][i][GROUP_PROPS][3])
167 bh 957
168     if data[CLASSES][i][GROUP_TYPE] == "default":
169     g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
170     elif data[CLASSES][i][GROUP_TYPE] == "range":
171 jonathan 1357 g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
172     data[CLASSES][i][GROUP_DATA][1]),
173 bh 957 props, data[CLASSES][i][GROUP_LABEL])
174     elif data[CLASSES][i][GROUP_TYPE] == "single":
175     g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
176     props, data[CLASSES][i][GROUP_LABEL])
177    
178     eq(group, g)
179    
180     i += 1
181    
182    
183    
184     class TestSingleLayer(LoadSessionTest):
185    
186 bh 1846 # Note: The use of &amp; and non-ascii characters is deliberate. We
187     # want to test whether the loading code handles that correctly.
188 bh 957 file_contents = '''\
189 bh 292 <?xml version="1.0" encoding="UTF-8"?>
190 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
191     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
192 bh 1848 title="Stra\xc3\x9fen &amp; Landmarken">
193 bh 1268 <fileshapesource filetype="shapefile" id="D1"
194     filename="../../Data/iceland/political.shp"/>
195 bh 1848 <map title="\xc3\x9cbersicht">
196 bh 1846 <projection epsg="32627" name="WGS 84 / UTM zone 27N">
197     <parameter value="datum=WGS84"/>
198     <parameter value="ellps=WGS84"/>
199 bh 1268 <parameter value="proj=utm"/>
200 bh 1846 <parameter value="units=m"/>
201     <parameter value="zone=27"/>
202 bh 1268 </projection>
203     <layer shapestore="D1" visible="true"
204 bh 1848 stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
205 bh 1268 fill="None"/>
206     </map>
207 bh 292 </session>
208     '''
209    
210 bh 957 def test(self):
211     """Load a session with a single map with a single layer"""
212     eq = self.assertEquals
213     session = load_session(self.filename())
214     self.session = session
215    
216     # Check the title
217 bh 1848 eq(session.Title(), "Stra\xdfen & Landmarken")
218 bh 957
219     # the session has one map.
220     maps = session.Maps()
221     eq(len(maps), 1)
222    
223     # Check the map's attributes
224     map = maps[0]
225 bh 1848 eq(map.Title(), "\xdcbersicht")
226 bh 1846 proj = map.GetProjection()
227     eq(proj.GetName(), "WGS 84 / UTM zone 27N")
228     eq(proj.EPSGCode(), "32627")
229     params = proj.GetAllParameters()
230     params.sort()
231     eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
232     "zone=27"])
233 bh 957
234     # the map has a single layer
235     layers = map.Layers()
236     eq(len(layers), 1)
237    
238     # Check the layer attributes
239     layer = layers[0]
240 bh 1848 eq(layer.Title(), "K\xfcste")
241 bh 1219 self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
242 bh 957 os.path.join(self.temp_dir(),
243     os.pardir, os.pardir,
244     "Data", "iceland",
245     "political.shp")))
246 jonathan 1347 eq(layer.GetClassification().GetDefaultFill(), Transparent)
247 bh 957 eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
248     eq(layer.Visible(), True)
249    
250 bh 1257 self.check_format()
251    
252 bh 957 self.session.Destroy()
253     self.session = None
254    
255 bh 1931 def test_leak(self):
256     """Test load_session for resource leaks
257 bh 957
258 bh 1931 The load_session function had a resource leak in that it created
259     cyclic references. The objects would have been eventually
260     collected by the garbage collector but too late. One symptom is
261     that when layers are removed so that the last normal reference
262     owned indirectly by the session to a shape store goes away, the
263     shape store is not actually removed from the session even though
264     the session only keeps weak references because there are still
265     references owned by the cyclic garbage.
266     """
267     session = load_session(self.filename())
268     self.session = session
269    
270     # sanity check
271     self.assertEquals(len(session.ShapeStores()), 1)
272    
273     # remove the map. The shapestore should go away too
274     session.RemoveMap(session.Maps()[0])
275     self.assertEquals(len(session.ShapeStores()), 0)
276    
277    
278 bh 1970 class TestNonAsciiColumnName(LoadSessionTest):
279    
280     file_contents = '''\
281     <?xml version="1.0" encoding="UTF-8"?>
282 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
283     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
284 bh 1970 title="Non ASCII column name test">
285     <fileshapesource filetype="shapefile" id="D1"
286     filename="TestNonAsciiColumnName.shp"/>
287     <map title="map">
288     <projection name="Some Projection">
289     <parameter value="datum=WGS84"/>
290     <parameter value="ellps=WGS84"/>
291     <parameter value="proj=utm"/>
292     <parameter value="units=m"/>
293     <parameter value="zone=27"/>
294     </projection>
295     <layer shapestore="D1" visible="true"
296     stroke="#000000" title="layer" stroke_width="1"
297     fill="None">
298     <classification field="Fl\xc3\xa4che" field_type="double">
299     <clnull label="">
300     <cldata stroke="#000000" stroke_width="1" fill="None"/>
301     </clnull>
302     </classification>
303     </layer>
304     </map>
305     </session>
306     '''
307    
308     def test(self):
309     """Load a session with a single map with a single layer"""
310    
311     # Create a shapefile and a dbffile with a non-ascii column name
312     dbffile = self.temp_file_name("TestNonAsciiColumnName.dbf")
313     shpfile = self.temp_file_name("TestNonAsciiColumnName.shp")
314     dbf = dbflib.create(dbffile)
315     dbf.add_field('Fl\xe4che', dbflib.FTDouble, 10, 5)
316     dbf.write_record(0, (0.0,))
317     dbf.close()
318     shp = shapelib.create(shpfile, shapelib.SHPT_POLYGON)
319     shp.write_object(-1, shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
320     [[(0,0), (10, 10), (10, 0),
321     (0, 0)]]))
322     shp.close()
323    
324     try:
325     session = load_session(self.filename())
326     except ValueError, v:
327     # Usually if the field name is not decoded properly the
328     # loading fails because the field type mentioned in the file
329     # is not None as returned from the layer for a non-existing
330     # column name so we check for that and report it as failure.
331     # Other exceptions are errors in the test case.
332     if str(v) == "xml field type differs from database!":
333     self.fail("Cannot load file with non-ascii column names")
334     else:
335     raise
336     self.session = session
337    
338     # In case Thuban could load the file anyway (i.e. no ValueError
339     # exception in load_session()), check explicitly whether the
340     # field name was decoded properly. The test will probably lead
341     # to a UnicodeError instead of a test failure so we check that
342     # too
343     layer = session.Maps()[0].Layers()[0]
344     try:
345     self.assertEquals(layer.GetClassificationColumn(), 'Fl\xe4che')
346     except UnicodeError:
347     # FIXME: Obviously this will have to change if Thuban ever
348     # supports unicode properly.
349     self.fail("Column name was not converted to a bytestring")
350    
351     # roundtrip check
352     self.check_format()
353    
354    
355 bh 957 class TestLayerVisibility(LoadSessionTest):
356    
357     file_contents = '''\
358 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
359 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
360     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
361 bh 1268 title="single map&amp;layer">
362     <fileshapesource filetype="shapefile" id="D1"
363     filename="../../Data/iceland/political.shp"/>
364     <map title="Test Map">
365     <projection name="Unknown">
366     <parameter value="zone=26"/>
367     <parameter value="proj=utm"/>
368     <parameter value="ellps=clrk66"/>
369     </projection>
370     <layer shapestore="D1" visible="false" stroke="#000000"
371     title="My Layer" stroke_width="1" fill="None"/>
372 bh 957 </map>
373     </session>
374     '''
375    
376     def test(self):
377     """Test that the visible flag is correctly loaded for a layer."""
378     eq = self.assertEquals
379     session = load_session(self.filename())
380     self.session = session
381     maps = session.Maps()
382     eq(len(maps), 1)
383     map = maps[0]
384     layers = map.Layers()
385     eq(len(layers), 1)
386     layer = layers[0]
387    
388     eq(layer.Visible(), False)
389    
390 bh 1257 self.check_format()
391 bh 957
392    
393 jan 2373 class TestSymbolSize(ClassificationTest):
394    
395     file_contents = '''\
396     <?xml version="1.0" encoding="UTF-8"?>
397     <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
398     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
399     <fileshapesource filetype="shapefile" id="D813968480" filename="../../Data/iceland/cultural_landmark-point.shp"/>
400     <map title="Iceland map">
401     <layer title="cultural_landmark-point" stroke_width="1" shapestore="D813968480" visible="true" stroke="#000000" fill="#000000">
402     <classification field="CLPTLABEL" field_type="string">
403     <clnull label="">
404     <cldata stroke="#000000" stroke_width="1" size="3" fill="#000000"/>
405     </clnull>
406     <clpoint label="" value="RUINS">
407     <cldata stroke="#000000" stroke_width="1" size="6" fill="#ffffff"/>
408     </clpoint>
409     <clpoint label="" value="FARM">
410     <cldata stroke="#000000" stroke_width="1" size="9" fill="#ffff00"/>
411     </clpoint>
412     </classification>
413     </layer>
414     </map>
415     </session>
416     '''
417    
418     def test(self):
419     """Test that the size attribute for point symbols is correctly
420     loaded for a layer."""
421     eq = self.assertEquals
422     session = load_session(self.filename())
423     self.session = session
424    
425     map = session.Maps()[0] # only one map in the sample
426    
427     expected = [("cultural_landmark-point", 2,
428     [("default", (), "",
429     ("#000000", 1, "#000000", 3)),
430     ("single", "RUINS", "",
431     ("#000000", 1, "#ffffff", 6)),
432     ("single", "FARM", "",
433     ("#000000", 1, "#ffff00", 9))])]
434    
435     self.TestLayers(map.Layers(), expected)
436    
437     self.check_format()
438    
439    
440 bh 957 class TestClassification(ClassificationTest):
441    
442     file_contents = '''\
443     <?xml version="1.0" encoding="UTF-8"?>
444 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
445     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
446 bh 1976 title="single map&amp;layer">
447     <fileshapesource filetype="shapefile" id="D138389860"
448     filename="../../Data/iceland/political.shp"/>
449     <fileshapesource filetype="shapefile" id="D138504492"
450     filename="../../Data/iceland/political.shp"/>
451     <map title="Test Map">
452     <projection name="">
453     <parameter value="zone=26"/>
454     <parameter value="proj=utm"/>
455     <parameter value="ellps=clrk66"/>
456     </projection>
457     <layer shapestore="D138389860" visible="true" stroke="#000000"
458     title="My Layer" stroke_width="1" fill="None">
459 jonathan 690 <classification field="POPYREG" field_type="string">
460 bh 1976 <clnull label="">
461 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
462     </clnull>
463 bh 1976 <clpoint label="" value="1">
464 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
465     </clpoint>
466 bh 1976 <clpoint label="" value="1">
467 jonathan 690 <cldata stroke="#000000" stroke_width="10" fill="None"/>
468     </clpoint>
469 bh 1976 <clpoint label="\xc3\x9cml\xc3\xa4uts"
470     value="\xc3\xa4\xc3\xb6\xc3\xbc">
471     <cldata stroke="#000000" stroke_width="1" fill="None"/>
472 bh 1417 </clpoint>
473 jonathan 690 </classification>
474     </layer>
475 bh 1976 <layer shapestore="D138504492" visible="true" stroke="#000000"
476     title="My Layer 2" stroke_width="2" fill="None">
477 jonathan 690 <classification field="AREA" field_type="double">
478 bh 1976 <clnull label="">
479 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
480     </clnull>
481 bh 1976 <clrange label="" range="[0;1[">
482 jonathan 692 <cldata stroke="#111111" stroke_width="1" fill="None"/>
483 jonathan 690 </clrange>
484 bh 1976 <clpoint label="" value="0.5">
485 jonathan 692 <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
486 jonathan 690 </clpoint>
487 bh 1976 <clrange label="" range="[-1;0[">
488 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
489     </clrange>
490 bh 1976 <clpoint label="" value="-0.5">
491 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
492     </clpoint>
493     </classification>
494     </layer>
495 bh 1976 </map>
496 jonathan 690 </session>
497     '''
498 bh 292
499 bh 957 def test(self):
500 bh 1247 """Load a Thuban session with a map and classified layers."""
501 bh 957 session = load_session(self.filename())
502     self.session = session
503    
504     map = self.session.Maps()[0] # only one map in the sample
505    
506 bh 1417 expected = [("My Layer", 3,
507 bh 957 [("default", (), "",
508     ("#000000", 1, "None")),
509     ("single", "1", "",
510     ("#000000", 2, "None")),
511     ("single", "1", "",
512 bh 1417 ("#000000", 10, "None")),
513     ("single", "\xe4\xf6\xfc", "\xdcml\xe4uts",
514     ("#000000", 1, "None"))]),
515 bh 957 ("My Layer 2", 4,
516     [("default", (), "",
517     ("#000000", 2, "None")),
518     ("range", (0, 1), "",
519     ("#111111", 1, "None")),
520     ("single", .5, "",
521     ("#000000", 1, "#111111")),
522     ("range", (-1, 0), "",
523     ("#000000", 1, "None")),
524     ("single", -.5, "",
525     ("#000000", 1, "None"))])]
526    
527     self.TestLayers(map.Layers(), expected)
528    
529 bh 1976 self.check_format()
530 bh 957
531 bh 1976
532 bh 957 class TestLabels(ClassificationTest):
533    
534     file_contents = '''\
535 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
536 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
537     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
538 bh 1268 title="single map&amp;layer">
539     <fileshapesource filetype="shapefile" id="D1"
540     filename="../../Data/iceland/political.shp"/>
541     <map title="Test Map">
542     <projection name="Unknown">
543     <parameter value="zone=26"/>
544     <parameter value="proj=utm"/>
545     <parameter value="ellps=clrk66"/>
546     </projection>
547     <layer shapestore="D1" visible="true" stroke="#000000"
548     title="My Layer" stroke_width="1" fill="None">
549 jonathan 690 <classification field="POPYREG" field_type="string">
550     <clnull label="hallo">
551     <cldata stroke="#000000" stroke_width="1" fill="None"/>
552     </clnull>
553     <clpoint label="welt" value="1">
554     <cldata stroke="#000000" stroke_width="2" fill="None"/>
555     </clpoint>
556     </classification>
557     </layer>
558     </map>
559     </session>
560     '''
561    
562 bh 957 def test(self):
563     """Load a session and test for reading the group labels."""
564     eq = self.assertEquals
565     session = load_session(self.filename())
566     self.session = session
567    
568     map = self.session.Maps()[0] # only one map in the sample
569    
570     expected = [("My Layer", 1,
571     [("default", (), "hallo",
572     ("#000000", 1, "None")),
573     ("single", "1", "welt",
574     ("#000000", 2, "None"))])]
575    
576     self.TestLayers(map.Layers(), expected)
577 bh 1257 self.check_format()
578 bh 957
579    
580     class TestLayerProjection(LoadSessionTest):
581    
582     file_contents = '''\
583 jonathan 746 <?xml version="1.0" encoding="UTF-8"?>
584 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
585     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
586 bh 1268 title="single map&amp;layer">
587     <fileshapesource filetype="shapefile" id="D2"
588     filename="../../Data/iceland/roads-line.shp"/>
589     <fileshapesource filetype="shapefile" id="D4"
590     filename="../../Data/iceland/political.shp"/>
591     <map title="Test Map">
592     <projection name="Unknown">
593     <parameter value="zone=26"/>
594     <parameter value="proj=utm"/>
595     <parameter value="ellps=clrk66"/>
596     </projection>
597     <layer shapestore="D4" visible="true" stroke="#000000"
598     title="My Layer" stroke_width="1" fill="None">
599     <projection name="hello">
600     <parameter value="zone=13"/>
601     <parameter value="proj=tmerc"/>
602     <parameter value="ellps=clrk66"/>
603     </projection>
604 jonathan 746 <classification field="POPYREG" field_type="string">
605     <clnull label="hallo">
606     <cldata stroke="#000000" stroke_width="1" fill="None"/>
607     </clnull>
608     <clpoint label="welt" value="1">
609     <cldata stroke="#000000" stroke_width="2" fill="None"/>
610     </clpoint>
611     </classification>
612     </layer>
613 bh 1268 <layer shapestore="D2" visible="true" stroke="#000000"
614     title="My Layer" stroke_width="1" fill="None">
615     <projection name="Unknown">
616     <parameter value="proj=lcc"/>
617 bh 1687 <parameter value="lat_1=10"/>
618     <parameter value="lat_2=20"/>
619 bh 1268 <parameter value="ellps=clrk66"/>
620     </projection>
621 jonathan 746 </layer>
622     </map>
623     </session>
624     '''
625    
626 bh 957 def test(self):
627     """Test loading layers with projections"""
628 bh 292 eq = self.assertEquals
629 jonathan 746 neq = self.assertNotEqual
630    
631 bh 957 session = load_session(self.filename())
632 jonathan 746 self.session = session
633    
634     map = self.session.Maps()[0] # only one map in the sample
635    
636     layers = map.Layers() # two layers in the sample
637    
638     # test layer with a named projection
639     proj = layers[0].GetProjection()
640     neq(proj, None)
641     eq(proj.GetName(), "hello")
642     eq(proj.GetParameter("proj"), "tmerc")
643     eq(proj.GetParameter("zone"), "13")
644     eq(proj.GetParameter("ellps"), "clrk66")
645    
646     # test layer with an unnamed projection
647     proj = layers[1].GetProjection()
648     neq(proj, None)
649     eq(proj.GetName(), "Unknown")
650     eq(proj.GetParameter("proj"), "lcc")
651 bh 1687 eq(proj.GetParameter("lat_1"), "10")
652     eq(proj.GetParameter("lat_2"), "20")
653 jonathan 746 eq(proj.GetParameter("ellps"), "clrk66")
654    
655 bh 1257 self.check_format()
656 bh 957
657 bh 1257
658 bh 957 class TestRasterLayer(LoadSessionTest):
659    
660     file_contents = '''\
661     <?xml version="1.0" encoding="UTF-8"?>
662 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
663     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
664 bh 1268 title="single map&amp;layer">
665     <map title="Test Map">
666 jonathan 2551 <rasterlayer visible="false" use_mask="true" filename="../../Data/iceland/island.tif"
667 bh 1268 title="My RasterLayer"/>
668 bh 957 </map>
669     </session>
670     '''
671    
672     def test(self):
673 jonathan 947 eq = self.assertEquals
674     neq = self.assertNotEqual
675    
676 bh 957 session = load_session(self.filename())
677 jonathan 947 self.session = session
678    
679     map = self.session.Maps()[0] # only one map in the sample
680    
681     layer = map.Layers()[0] # one layer in the sample
682    
683 jonathan 2551 layer.SetUseMask(True)
684    
685 jonathan 947 eq(layer.Title(), "My RasterLayer")
686     self.failIf(layer.Visible())
687     self.failUnless(filenames_equal(layer.GetImageFilename(),
688     os.path.join(self.temp_dir(),
689     os.pardir, os.pardir,
690     "Data", "iceland",
691     "island.tif")))
692 bh 1257 self.check_format()
693 jonathan 947
694 bh 1268
695     class TestJoinedTable(LoadSessionTest):
696    
697     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
698 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
699     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="A Joined Table session">
700 bh 1282 <fileshapesource filetype="shapefile" id="D137227612"
701     filename="../../Data/iceland/roads-line.shp"/>
702     <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
703     title="Some Title"/>
704 bh 1375 <jointable id="D136169900" title="Joined"
705     right="D136171140" left="D137227612"
706     leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
707     jointype="LEFT OUTER"/>
708 bh 1282 <derivedshapesource table="D136169900" shapesource="D137227612"
709     id="D136170932"/>
710 bh 1268 <map title="Test Map">
711 bh 1282 <layer shapestore="D136170932" visible="true" stroke="#000000"
712     title="My Layer" stroke_width="1" fill="None"/>
713 bh 1268 </map>
714 bh 1282 </session>
715     '''
716 bh 1268
717     def setUp(self):
718     """Extend inherited method to create the dbffile for the join"""
719     LoadSessionTest.setUp(self)
720     dbffile = self.temp_file_name("load_joinedtable.dbf")
721     dbf = dbflib.create(dbffile)
722     dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
723     dbf.add_field("TEXT", dbflib.FTString, 10, 0)
724     dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
725     dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
726     dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
727     dbf.close()
728    
729     def test(self):
730     """Test loading a session containing a joined table"""
731     session = load_session(self.filename())
732     self.session = session
733    
734     tables = session.Tables()
735     self.assertEquals(len(tables), 3)
736     # FIXME: The tests shouldn't assume a certain order of the tables
737     self.assertEquals(tables[0].Title(), "Some Title")
738     self.assertEquals(tables[1].Title(), "Joined")
739 bh 1375 self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
740 bh 1282 self.check_format()
741 bh 1268
742    
743 bh 2034 class TestLabelLayer(LoadSessionTest):
744 bh 1646
745 bh 2034 # Note that the labels deliberately contain non-ascii characters to
746     # test whether they're supported correctly.
747    
748     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
749 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
750     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
751 bh 2034 <fileshapesource filetype="shapefile" id="D145265052"
752     filename="../../Data/iceland/political.shp"/>
753     <fileshapesource filetype="shapefile" id="D145412868"
754     filename="../../Data/iceland/cultural_landmark-point.shp"/>
755     <map title="Iceland map">
756     <projection name="Unknown">
757     <parameter value="zone=26"/>
758     <parameter value="proj=utm"/>
759     <parameter value="ellps=clrk66"/>
760     </projection>
761     <layer shapestore="D145265052" visible="true" stroke="#000000"
762     title="political" stroke_width="1" fill="#c0c0c0">
763     <projection name="Geographic">
764     <parameter value="proj=latlong"/>
765     <parameter value="to_meter=0.017453"/>
766     <parameter value="ellps=clrk66"/>
767     </projection>
768     </layer>
769     <layer shapestore="D145412868" visible="true" stroke="#000000"
770     title="landmarks" stroke_width="1" fill="#ffff00">
771     <projection name="Geographic">
772     <parameter value="proj=latlong"/>
773     <parameter value="to_meter=0.017453"/>
774     <parameter value="ellps=clrk66"/>
775     </projection>
776     </layer>
777     <labellayer>
778     <label x="-21.5" y="64.25" text="RUINS"
779     halign="left" valign="center"/>
780     <label x="-15.125" y="64.75" text="H\xc3\xbctte"
781     halign="right" valign="top"/>
782     </labellayer>
783     </map>
784     </session>
785     '''
786    
787     def test(self):
788     """Test loading a session with a label layer"""
789     session = load_session(self.filename())
790     self.session = session
791    
792     label_layer = self.session.Maps()[0].LabelLayer()
793     expected_labels = [(-21.5, 64.25, "RUINS", ALIGN_LEFT, ALIGN_CENTER),
794     (-15.125, 64.75, "H\xfctte", ALIGN_RIGHT, ALIGN_TOP),
795     ]
796     for label, values in zip(label_layer.Labels(), expected_labels):
797     self.assertEquals((label.x, label.y, label.text, label.halign,
798     label.valign),
799     values)
800     self.check_format()
801    
802    
803 bh 1646 class TestPostGISLayer(LoadSessionTest):
804    
805     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
806 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
807     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
808 bh 1646 title="unnamed session">
809     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
810     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
811 bh 2104 <dbshapesource id="D143149420" dbconn="D142684948"
812     tablename="landmarks_point_id" id_column="point_id"
813     geometry_column="the_geom" />
814 bh 1646 <map title="unnamed map">
815     <layer shapestore="D143149420" visible="true" stroke="#000000"
816     title="landmarks" stroke_width="1" fill="None"/>
817     </map>
818     </session>
819     '''
820    
821     def setUp(self):
822     """Extend the inherited method to start the postgis server
823    
824     Furthermore, patch the file contents with the real postgis db
825     information
826     """
827     postgissupport.skip_if_no_postgis()
828     self.server = postgissupport.get_test_server()
829     self.postgisdb = self.server.get_default_static_data_db()
830    
831     self.file_contents = self.__class__.file_contents % {
832     "dbname": self.postgisdb.dbname,
833     "user": self.server.user_name,
834     "port": self.server.port,
835     "host": self.server.host}
836     LoadSessionTest.setUp(self)
837    
838     def test(self):
839     """Test loading a session containing a postgis shapestore"""
840     session = load_session(self.filename())
841     self.session = session
842     connections = session.DBConnections()
843     self.assertEquals(len(connections), 1)
844     conn = connections[0]
845     for attr, value in [("host", self.server.host),
846     ("port", str(self.server.port)),
847     ("user", self.server.user_name),
848     ("dbname", self.postgisdb.dbname)]:
849     self.assertEquals(getattr(conn, attr), value)
850     layer = session.Maps()[0].Layers()[0]
851     self.failUnless(layer.ShapeStore().DBConnection() is conn)
852    
853    
854     class TestPostGISLayerPassword(LoadSessionTest):
855    
856     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
857 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
858     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
859 bh 1646 title="unnamed session">
860     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
861     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
862     <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
863     <map title="unnamed map">
864     <layer shapestore="D143149420" visible="true" stroke="#000000"
865     title="landmarks" stroke_width="1" fill="None"/>
866     </map>
867     </session>
868     '''
869    
870     def setUp(self):
871     """Extend the inherited method to start the postgis server
872    
873     Furthermore, patch the file contents with the real postgis db
874     information
875     """
876     postgissupport.skip_if_no_postgis()
877     self.server = postgissupport.get_test_server()
878     self.postgisdb = self.server.get_default_static_data_db()
879    
880     self.file_contents = self.__class__.file_contents % {
881     "dbname": self.postgisdb.dbname,
882     "user": self.server.user_name,
883     "port": self.server.port,
884     "host": self.server.host}
885     LoadSessionTest.setUp(self)
886    
887     self.db_connection_callback_called = False
888     self.server.require_authentication(True)
889    
890     def tearDown(self):
891     """Extend the inherited method to switch off postgresql authentication
892     """
893     self.server.require_authentication(False)
894     LoadSessionTest.tearDown(self)
895    
896     def db_connection_callback(self, params, message):
897     """Implementation of Thuban.Model.hooks.query_db_connection_parameters
898     """
899     self.assertEquals(params,
900     {"dbname": self.postgisdb.dbname,
901     "user": self.server.user_name,
902     "port": str(self.server.port),
903     "host": self.server.host})
904     self.db_connection_callback_called = True
905     params = params.copy()
906     params["password"] = self.server.user_password
907     return params
908    
909     def test_with_callback(self):
910     """Test loading a session with postgis, authentication and a callback
911     """
912     session = load_session(self.filename(),
913     db_connection_callback = self.db_connection_callback)
914     self.session = session
915     connections = session.DBConnections()
916     self.assertEquals(len(connections), 1)
917     conn = connections[0]
918     for attr, value in [("host", self.server.host),
919     ("port", str(self.server.port)),
920     ("user", self.server.user_name),
921     ("dbname", self.postgisdb.dbname)]:
922     self.assertEquals(getattr(conn, attr), value)
923     layer = session.Maps()[0].Layers()[0]
924     self.failUnless(layer.ShapeStore().DBConnection() is conn)
925     self.failUnless(self.db_connection_callback_called)
926    
927     def test_without_callback(self):
928     """Test loading a session with postgis, authentication and no callback
929     """
930     # A password is required and there's no callback, so we should
931     # get a ConnectionError
932     self.assertRaises(ConnectionError, load_session, self.filename())
933    
934     def test_cancel(self):
935     """Test loading a session with postgis and cancelling authentication
936     """
937     def cancel(*args):
938     self.db_connection_callback_called = True
939     return None
940    
941     # If the user cancels, i.e. if the callbakc returns None, a
942     # LoadCancelled exception is raised.
943     self.assertRaises(LoadCancelled,
944     load_session, self.filename(), cancel)
945     self.failUnless(self.db_connection_callback_called)
946    
947    
948 bh 1268 class TestLoadError(LoadSessionTest):
949    
950     file_contents = '''\
951     <?xml version="1.0" encoding="UTF-8"?>
952 bh 2104 <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
953     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
954 bh 1268 title="single map&amp;layer">
955     <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
956     <map title="Test Map">
957     <projection name="Unknown">
958     <parameter value="zone=26"/>
959     <parameter value="proj=utm"/>
960     <parameter value="ellps=clrk66"/>
961     </projection>
962     <layer shapestore="D1" visible="true"
963     stroke="#000000" title="My Layer" stroke_width="1"
964     fill="None"/>
965     </map>
966     </session>
967     '''
968    
969     def test(self):
970     """Test loading a session missing a required attribute"""
971     # Don't use assertRaises to make sure that if a session is
972     # actually returned it gets destroyed properly.
973     try:
974     self.session = load_session(self.filename())
975     except LoadError, value:
976 bh 1642 # Check the actual messge in value to make sure the
977     # LoadError really was about the missing attribute
978     self.assertEquals(str(value),
979     "Element "
980 bh 2104 "(u'http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd',"
981 bh 1642 " u'fileshapesource') requires an attribute 'filetype'")
982 bh 1268 else:
983     self.fail("Missing filetype attribute doesn't raise LoadError")
984    
985 frank 2446 class Shapefile_CallBack:
986    
987     def __init__(self, params):
988     """Initialize the callback return values.
989    
990     params must be a dictionary of the potential CB modes (keys),
991     with lists of tuples of return values as values.
992     Depending on the test the callback can be called multiple,
993     each time a return value is poped from the list
994     """
995    
996     self.params = params
997    
998    
999     def s_cb(self, filename, mode = None, second_try= 0):
1000     if self.params.has_key(mode):
1001     return self.params[mode].pop(0)
1002     else:
1003     raise LoadError
1004    
1005     class TestAltPath(LoadSessionTest):
1006    
1007     """Test the various cases in the alternative path feature.
1008    
1009     The test checks the reasonable cases:
1010     - First recognition of a path error, fixed with user interaction.
1011     - First recognition of a path error, load cancelled.
1012     - Path error fixed from list, confirmed by user.
1013     - Path error fixed from list, changed by user.
1014     - Path error fixed from list, cancelled by user.
1015     - Path error wrongly fixed from list, manual fix forced.
1016     """
1017    
1018     file_contents = '''\
1019     <?xml version="1.0" encoding="UTF-8"?>
1020     <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
1021 frank 2456 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="AltPath Test session">
1022 frank 2446 <fileshapesource filetype="shapefile" id="D1108450956" filename="../../Data/iceland/political.shp"/>
1023     <fileshapesource filetype="shapefile" id="D1108900076" filename="../Data/iceland/roads-line.shp"/>
1024     <fileshapesource filetype="shapefile" id="D1108947244" filename="../../Data/iceland/cultural_landmark-point.shp"/>
1025     <map title="not the iceland map">
1026     <layer title="political" stroke_width="1" shapestore="D1108450956" visible="true" stroke="#000000" fill="#c0c0c0"/>
1027     <layer title="roads-line" stroke_width="1" shapestore="D1108900076" visible="true" stroke="#000000" fill="None"/>
1028     <layer title="something else" stroke_width="1" shapestore="D1108947244" visible="true" stroke="#000000" fill="None"/>
1029     </map>
1030     </session>
1031     '''
1032    
1033 frank 2456 def checkSession(self, session):
1034     """Check if session has been loaded successfully."""
1035    
1036     eq = self.assertEquals
1037    
1038     map = session.Maps()[0]
1039     layers = map.Layers()
1040    
1041     eq("AltPath Test session", session.Title())
1042     eq("not the iceland map", map.Title())
1043     eq(3,len(layers))
1044     eq("political",layers[0].Title())
1045     eq("roads-line",layers[1].Title())
1046     eq("something else",layers[2].Title())
1047    
1048 frank 2446 def test_01_single_path_error_fix(self):
1049     """Test single file path error fix."""
1050     # The usual initial case
1051     s_cb = Shapefile_CallBack({
1052     "search": [("../Data/iceland/roads-line.shp",0)],
1053     "check": [(None, None)]})
1054     self.session = load_session(self.filename(),
1055     shapefile_callback =s_cb.s_cb)
1056 frank 2456 self.checkSession(self.session)
1057    
1058 frank 2446 def test_02_path_error_fix_from_list(self):
1059     """Test single file path error fix."""
1060     # This represents the usual case for "from_list"
1061     s_cb = Shapefile_CallBack({
1062     "search": [("../Data/iceland/roads-line.shp",1)],
1063     "check": [(os.path.abspath("../Data/iceland/roads-line.shp"),1)]
1064     })
1065     self.session = load_session(self.filename(),
1066     shapefile_callback =s_cb.s_cb)
1067 frank 2456 self.checkSession(self.session)
1068 frank 2446
1069     def test_03_single_path_error_cancelled(self):
1070     """Test alternative path cancelled."""
1071     s_cb = Shapefile_CallBack({
1072     "search": [(None,0)],
1073     "check": [(None, None)]})
1074     self.assertRaises(LoadCancelled,
1075     load_session, self.filename(), None, s_cb.s_cb)
1076    
1077     def test_04_path_error_fix_from_list_cancelled(self):
1078     """Test alternative path from list cancelled."""
1079     s_cb = Shapefile_CallBack({
1080     "search": [("../Data/iceland/roads-line.shp",1)],
1081     "check": [(None,1)]
1082     })
1083     self.assertRaises(LoadCancelled,
1084     load_session, self.filename(), None, s_cb.s_cb)
1085    
1086     def test_05_path_error_fix_from_list_changed(self):
1087     """Test alternative path from list changed."""
1088     s_cb = Shapefile_CallBack({
1089     "search": [("../Data/iceland/roads-line.shp",1)],
1090     "check": [("../Data/iceland/roads-line.shp",0)]
1091     })
1092     self.session = load_session(self.filename(),
1093     shapefile_callback =s_cb.s_cb)
1094 frank 2456 self.checkSession(self.session)
1095 frank 2446
1096     def test_06_path_error_fix_from_list_fails(self):
1097     """Test alternative path recovery from list."""
1098     s_cb = Shapefile_CallBack({
1099     "search": [("../wrong/iceland/roads-line.shp",1),
1100     ("../Data/iceland/roads-line.shp",0)],
1101     "check": [(None,None)]
1102     })
1103     self.session = load_session(self.filename(),
1104     shapefile_callback =s_cb.s_cb)
1105     self.assertRaises(IndexError,
1106     s_cb.s_cb, None, "search")
1107    
1108    
1109    
1110 bh 292 if __name__ == "__main__":
1111 bh 1683 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