/[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 2034 - (hide annotations)
Mon Dec 22 16:35:16 2003 UTC (21 years, 2 months ago) by bh
Original Path: trunk/thuban/test/test_load.py
File MIME type: text/x-python
File size: 35541 byte(s)
* Thuban/Model/load.py (SessionLoader.start_label): Make sure the
alignment flags are byte strings not unicode and that they have
valid values

* test/test_load.py (TestLabelLayer): New. Test loading (and
indirectly saving) of maps with labels.

1 bh 765 # Copyright (c) 2002, 2003 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     to the last released version for the first, the tests here should be
20 bh 1257 copied to the version specific test file. The round-trip tests which
21     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 1970
57 bh 292 def filenames_equal(name1, name2):
58     """Return true if the filenames name1 and name2 are equal.
59    
60     On systems where it is available, simply use os.path.samefile,
61     otherwise return whether the normalized versions of the filenames
62     according to os.path.normpath are equal.
63     """
64     if hasattr(os.path, "samefile"):
65     return os.path.samefile(name1, name2)
66     return os.path.normpath(name1) == os.path.normpath(name2)
67    
68    
69 bh 957
70     class LoadSessionTest(support.FileLoadTestCase):
71    
72     """Base class for .thuban file loading tests
73    
74     Basically the same as the FileLoadTestCase, except that all tests
75     use the '.thuban' extension by default and that setUp and tearDown
76     handle sessions.
77     """
78    
79     file_extension = ".thuban"
80    
81     def setUp(self):
82     """Create the test files"""
83     support.FileLoadTestCase.setUp(self)
84     self.session = None
85    
86     def tearDown(self):
87     if self.session is not None:
88     self.session.Destroy()
89     self.session = None
90    
91 bh 1268
92 bh 2004 dtd = "http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
93 bh 1268 thubanids = [((dtd, n), (None, "id")) for n in
94     ["fileshapesource", "filetable", "jointable",
95     "derivedshapesource"]]
96     thubanidrefs = [((dtd, n), (None, m)) for n, m in
97     [("layer", "shapestore"),
98     ("jointable", "left"),
99     ("jointable", "right"),
100     ("derivedshapesource", "table"),
101     ("derivedshapesource", "shapesource")]]
102 bh 1989
103     # The filenames in the tests should be understandable on all
104     # currently supported platforms so filenames is an empty list
105     filenames = []
106    
107 bh 1268 del n, m, dtd
108    
109 bh 1257 def check_format(self):
110     """Check whether the file we loaded from matches the one that
111     would be written. Call this from each test case after loading
112     the session
113     """
114     filename = self.temp_file_name(self.id() + ".roundtrip.thuban")
115     save_session(self.session, filename)
116 bh 1268 el1 = sax_eventlist(filename = filename, ids = self.thubanids,
117 bh 1683 idrefs = self.thubanidrefs,
118     filenames = self.filenames)
119 bh 1268 el2 = sax_eventlist(filename = self.filename(), ids = self.thubanids,
120 bh 1683 idrefs = self.thubanidrefs,
121     filenames = self.filenames)
122 bh 1268 if 0:
123     for a, b in zip(el1, el2):
124     print a != b and "***************" or ""
125     print a
126     print b
127     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    
166     if data[CLASSES][i][GROUP_TYPE] == "default":
167     g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
168     elif data[CLASSES][i][GROUP_TYPE] == "range":
169 jonathan 1357 g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
170     data[CLASSES][i][GROUP_DATA][1]),
171 bh 957 props, data[CLASSES][i][GROUP_LABEL])
172     elif data[CLASSES][i][GROUP_TYPE] == "single":
173     g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
174     props, data[CLASSES][i][GROUP_LABEL])
175    
176     eq(group, g)
177    
178     i += 1
179    
180    
181    
182     class TestSingleLayer(LoadSessionTest):
183    
184 bh 1846 # Note: The use of &amp; and non-ascii characters is deliberate. We
185     # want to test whether the loading code handles that correctly.
186 bh 957 file_contents = '''\
187 bh 292 <?xml version="1.0" encoding="UTF-8"?>
188 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
189 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
190 bh 1848 title="Stra\xc3\x9fen &amp; Landmarken">
191 bh 1268 <fileshapesource filetype="shapefile" id="D1"
192     filename="../../Data/iceland/political.shp"/>
193 bh 1848 <map title="\xc3\x9cbersicht">
194 bh 1846 <projection epsg="32627" name="WGS 84 / UTM zone 27N">
195     <parameter value="datum=WGS84"/>
196     <parameter value="ellps=WGS84"/>
197 bh 1268 <parameter value="proj=utm"/>
198 bh 1846 <parameter value="units=m"/>
199     <parameter value="zone=27"/>
200 bh 1268 </projection>
201     <layer shapestore="D1" visible="true"
202 bh 1848 stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
203 bh 1268 fill="None"/>
204     </map>
205 bh 292 </session>
206     '''
207    
208 bh 957 def test(self):
209     """Load a session with a single map with a single layer"""
210     eq = self.assertEquals
211     session = load_session(self.filename())
212     self.session = session
213    
214     # Check the title
215 bh 1848 eq(session.Title(), "Stra\xdfen & Landmarken")
216 bh 957
217     # the session has one map.
218     maps = session.Maps()
219     eq(len(maps), 1)
220    
221     # Check the map's attributes
222     map = maps[0]
223 bh 1848 eq(map.Title(), "\xdcbersicht")
224 bh 1846 proj = map.GetProjection()
225     eq(proj.GetName(), "WGS 84 / UTM zone 27N")
226     eq(proj.EPSGCode(), "32627")
227     params = proj.GetAllParameters()
228     params.sort()
229     eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
230     "zone=27"])
231 bh 957
232     # the map has a single layer
233     layers = map.Layers()
234     eq(len(layers), 1)
235    
236     # Check the layer attributes
237     layer = layers[0]
238 bh 1848 eq(layer.Title(), "K\xfcste")
239 bh 1219 self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
240 bh 957 os.path.join(self.temp_dir(),
241     os.pardir, os.pardir,
242     "Data", "iceland",
243     "political.shp")))
244 jonathan 1347 eq(layer.GetClassification().GetDefaultFill(), Transparent)
245 bh 957 eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
246     eq(layer.Visible(), True)
247    
248 bh 1257 self.check_format()
249    
250 bh 957 self.session.Destroy()
251     self.session = None
252    
253 bh 1931 def test_leak(self):
254     """Test load_session for resource leaks
255 bh 957
256 bh 1931 The load_session function had a resource leak in that it created
257     cyclic references. The objects would have been eventually
258     collected by the garbage collector but too late. One symptom is
259     that when layers are removed so that the last normal reference
260     owned indirectly by the session to a shape store goes away, the
261     shape store is not actually removed from the session even though
262     the session only keeps weak references because there are still
263     references owned by the cyclic garbage.
264     """
265     session = load_session(self.filename())
266     self.session = session
267    
268     # sanity check
269     self.assertEquals(len(session.ShapeStores()), 1)
270    
271     # remove the map. The shapestore should go away too
272     session.RemoveMap(session.Maps()[0])
273     self.assertEquals(len(session.ShapeStores()), 0)
274    
275    
276 bh 1970 class TestNonAsciiColumnName(LoadSessionTest):
277    
278     file_contents = '''\
279     <?xml version="1.0" encoding="UTF-8"?>
280     <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
281 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
282 bh 1970 title="Non ASCII column name test">
283     <fileshapesource filetype="shapefile" id="D1"
284     filename="TestNonAsciiColumnName.shp"/>
285     <map title="map">
286     <projection name="Some Projection">
287     <parameter value="datum=WGS84"/>
288     <parameter value="ellps=WGS84"/>
289     <parameter value="proj=utm"/>
290     <parameter value="units=m"/>
291     <parameter value="zone=27"/>
292     </projection>
293     <layer shapestore="D1" visible="true"
294     stroke="#000000" title="layer" stroke_width="1"
295     fill="None">
296     <classification field="Fl\xc3\xa4che" field_type="double">
297     <clnull label="">
298     <cldata stroke="#000000" stroke_width="1" fill="None"/>
299     </clnull>
300     </classification>
301     </layer>
302     </map>
303     </session>
304     '''
305    
306     def test(self):
307     """Load a session with a single map with a single layer"""
308    
309     # Create a shapefile and a dbffile with a non-ascii column name
310     dbffile = self.temp_file_name("TestNonAsciiColumnName.dbf")
311     shpfile = self.temp_file_name("TestNonAsciiColumnName.shp")
312     dbf = dbflib.create(dbffile)
313     dbf.add_field('Fl\xe4che', dbflib.FTDouble, 10, 5)
314     dbf.write_record(0, (0.0,))
315     dbf.close()
316     shp = shapelib.create(shpfile, shapelib.SHPT_POLYGON)
317     shp.write_object(-1, shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
318     [[(0,0), (10, 10), (10, 0),
319     (0, 0)]]))
320     shp.close()
321    
322     try:
323     session = load_session(self.filename())
324     except ValueError, v:
325     # Usually if the field name is not decoded properly the
326     # loading fails because the field type mentioned in the file
327     # is not None as returned from the layer for a non-existing
328     # column name so we check for that and report it as failure.
329     # Other exceptions are errors in the test case.
330     if str(v) == "xml field type differs from database!":
331     self.fail("Cannot load file with non-ascii column names")
332     else:
333     raise
334     self.session = session
335    
336     # In case Thuban could load the file anyway (i.e. no ValueError
337     # exception in load_session()), check explicitly whether the
338     # field name was decoded properly. The test will probably lead
339     # to a UnicodeError instead of a test failure so we check that
340     # too
341     layer = session.Maps()[0].Layers()[0]
342     try:
343     self.assertEquals(layer.GetClassificationColumn(), 'Fl\xe4che')
344     except UnicodeError:
345     # FIXME: Obviously this will have to change if Thuban ever
346     # supports unicode properly.
347     self.fail("Column name was not converted to a bytestring")
348    
349     # roundtrip check
350     self.check_format()
351    
352    
353 bh 957 class TestLayerVisibility(LoadSessionTest):
354    
355     file_contents = '''\
356 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
357 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
358 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
359 bh 1268 title="single map&amp;layer">
360     <fileshapesource filetype="shapefile" id="D1"
361     filename="../../Data/iceland/political.shp"/>
362     <map title="Test Map">
363     <projection name="Unknown">
364     <parameter value="zone=26"/>
365     <parameter value="proj=utm"/>
366     <parameter value="ellps=clrk66"/>
367     </projection>
368     <layer shapestore="D1" visible="false" stroke="#000000"
369     title="My Layer" stroke_width="1" fill="None"/>
370 bh 957 </map>
371     </session>
372     '''
373    
374     def test(self):
375     """Test that the visible flag is correctly loaded for a layer."""
376     eq = self.assertEquals
377     session = load_session(self.filename())
378     self.session = session
379     maps = session.Maps()
380     eq(len(maps), 1)
381     map = maps[0]
382     layers = map.Layers()
383     eq(len(layers), 1)
384     layer = layers[0]
385    
386     eq(layer.Visible(), False)
387    
388 bh 1257 self.check_format()
389 bh 957
390    
391     class TestClassification(ClassificationTest):
392    
393     file_contents = '''\
394     <?xml version="1.0" encoding="UTF-8"?>
395 bh 1976 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
396 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
397 bh 1976 title="single map&amp;layer">
398     <fileshapesource filetype="shapefile" id="D138389860"
399     filename="../../Data/iceland/political.shp"/>
400     <fileshapesource filetype="shapefile" id="D138504492"
401     filename="../../Data/iceland/political.shp"/>
402     <map title="Test Map">
403     <projection name="">
404     <parameter value="zone=26"/>
405     <parameter value="proj=utm"/>
406     <parameter value="ellps=clrk66"/>
407     </projection>
408     <layer shapestore="D138389860" visible="true" stroke="#000000"
409     title="My Layer" stroke_width="1" fill="None">
410 jonathan 690 <classification field="POPYREG" field_type="string">
411 bh 1976 <clnull label="">
412 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
413     </clnull>
414 bh 1976 <clpoint label="" value="1">
415 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
416     </clpoint>
417 bh 1976 <clpoint label="" value="1">
418 jonathan 690 <cldata stroke="#000000" stroke_width="10" fill="None"/>
419     </clpoint>
420 bh 1976 <clpoint label="\xc3\x9cml\xc3\xa4uts"
421     value="\xc3\xa4\xc3\xb6\xc3\xbc">
422     <cldata stroke="#000000" stroke_width="1" fill="None"/>
423 bh 1417 </clpoint>
424 jonathan 690 </classification>
425     </layer>
426 bh 1976 <layer shapestore="D138504492" visible="true" stroke="#000000"
427     title="My Layer 2" stroke_width="2" fill="None">
428 jonathan 690 <classification field="AREA" field_type="double">
429 bh 1976 <clnull label="">
430 jonathan 690 <cldata stroke="#000000" stroke_width="2" fill="None"/>
431     </clnull>
432 bh 1976 <clrange label="" range="[0;1[">
433 jonathan 692 <cldata stroke="#111111" stroke_width="1" fill="None"/>
434 jonathan 690 </clrange>
435 bh 1976 <clpoint label="" value="0.5">
436 jonathan 692 <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
437 jonathan 690 </clpoint>
438 bh 1976 <clrange label="" range="[-1;0[">
439 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
440     </clrange>
441 bh 1976 <clpoint label="" value="-0.5">
442 jonathan 690 <cldata stroke="#000000" stroke_width="1" fill="None"/>
443     </clpoint>
444     </classification>
445     </layer>
446 bh 1976 </map>
447 jonathan 690 </session>
448     '''
449 bh 292
450 bh 957 def test(self):
451 bh 1247 """Load a Thuban session with a map and classified layers."""
452 bh 957 session = load_session(self.filename())
453     self.session = session
454    
455     map = self.session.Maps()[0] # only one map in the sample
456    
457 bh 1417 expected = [("My Layer", 3,
458 bh 957 [("default", (), "",
459     ("#000000", 1, "None")),
460     ("single", "1", "",
461     ("#000000", 2, "None")),
462     ("single", "1", "",
463 bh 1417 ("#000000", 10, "None")),
464     ("single", "\xe4\xf6\xfc", "\xdcml\xe4uts",
465     ("#000000", 1, "None"))]),
466 bh 957 ("My Layer 2", 4,
467     [("default", (), "",
468     ("#000000", 2, "None")),
469     ("range", (0, 1), "",
470     ("#111111", 1, "None")),
471     ("single", .5, "",
472     ("#000000", 1, "#111111")),
473     ("range", (-1, 0), "",
474     ("#000000", 1, "None")),
475     ("single", -.5, "",
476     ("#000000", 1, "None"))])]
477    
478     self.TestLayers(map.Layers(), expected)
479    
480 bh 1976 self.check_format()
481 bh 957
482 bh 1976
483 bh 957 class TestLabels(ClassificationTest):
484    
485     file_contents = '''\
486 jonathan 690 <?xml version="1.0" encoding="UTF-8"?>
487 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
488 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
489 bh 1268 title="single map&amp;layer">
490     <fileshapesource filetype="shapefile" id="D1"
491     filename="../../Data/iceland/political.shp"/>
492     <map title="Test Map">
493     <projection name="Unknown">
494     <parameter value="zone=26"/>
495     <parameter value="proj=utm"/>
496     <parameter value="ellps=clrk66"/>
497     </projection>
498     <layer shapestore="D1" visible="true" stroke="#000000"
499     title="My Layer" stroke_width="1" fill="None">
500 jonathan 690 <classification field="POPYREG" field_type="string">
501     <clnull label="hallo">
502     <cldata stroke="#000000" stroke_width="1" fill="None"/>
503     </clnull>
504     <clpoint label="welt" value="1">
505     <cldata stroke="#000000" stroke_width="2" fill="None"/>
506     </clpoint>
507     </classification>
508     </layer>
509     </map>
510     </session>
511     '''
512    
513 bh 957 def test(self):
514     """Load a session and test for reading the group labels."""
515     eq = self.assertEquals
516     session = load_session(self.filename())
517     self.session = session
518    
519     map = self.session.Maps()[0] # only one map in the sample
520    
521     expected = [("My Layer", 1,
522     [("default", (), "hallo",
523     ("#000000", 1, "None")),
524     ("single", "1", "welt",
525     ("#000000", 2, "None"))])]
526    
527     self.TestLayers(map.Layers(), expected)
528 bh 1257 self.check_format()
529 bh 957
530    
531     class TestLayerProjection(LoadSessionTest):
532    
533     file_contents = '''\
534 jonathan 746 <?xml version="1.0" encoding="UTF-8"?>
535 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
536 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
537 bh 1268 title="single map&amp;layer">
538     <fileshapesource filetype="shapefile" id="D2"
539     filename="../../Data/iceland/roads-line.shp"/>
540     <fileshapesource filetype="shapefile" id="D4"
541     filename="../../Data/iceland/political.shp"/>
542     <map title="Test Map">
543     <projection name="Unknown">
544     <parameter value="zone=26"/>
545     <parameter value="proj=utm"/>
546     <parameter value="ellps=clrk66"/>
547     </projection>
548     <layer shapestore="D4" visible="true" stroke="#000000"
549     title="My Layer" stroke_width="1" fill="None">
550     <projection name="hello">
551     <parameter value="zone=13"/>
552     <parameter value="proj=tmerc"/>
553     <parameter value="ellps=clrk66"/>
554     </projection>
555 jonathan 746 <classification field="POPYREG" field_type="string">
556     <clnull label="hallo">
557     <cldata stroke="#000000" stroke_width="1" fill="None"/>
558     </clnull>
559     <clpoint label="welt" value="1">
560     <cldata stroke="#000000" stroke_width="2" fill="None"/>
561     </clpoint>
562     </classification>
563     </layer>
564 bh 1268 <layer shapestore="D2" visible="true" stroke="#000000"
565     title="My Layer" stroke_width="1" fill="None">
566     <projection name="Unknown">
567     <parameter value="proj=lcc"/>
568 bh 1687 <parameter value="lat_1=10"/>
569     <parameter value="lat_2=20"/>
570 bh 1268 <parameter value="ellps=clrk66"/>
571     </projection>
572 jonathan 746 </layer>
573     </map>
574     </session>
575     '''
576    
577 bh 957 def test(self):
578     """Test loading layers with projections"""
579 bh 292 eq = self.assertEquals
580 jonathan 746 neq = self.assertNotEqual
581    
582 bh 957 session = load_session(self.filename())
583 jonathan 746 self.session = session
584    
585     map = self.session.Maps()[0] # only one map in the sample
586    
587     layers = map.Layers() # two layers in the sample
588    
589     # test layer with a named projection
590     proj = layers[0].GetProjection()
591     neq(proj, None)
592     eq(proj.GetName(), "hello")
593     eq(proj.GetParameter("proj"), "tmerc")
594     eq(proj.GetParameter("zone"), "13")
595     eq(proj.GetParameter("ellps"), "clrk66")
596    
597     # test layer with an unnamed projection
598     proj = layers[1].GetProjection()
599     neq(proj, None)
600     eq(proj.GetName(), "Unknown")
601     eq(proj.GetParameter("proj"), "lcc")
602 bh 1687 eq(proj.GetParameter("lat_1"), "10")
603     eq(proj.GetParameter("lat_2"), "20")
604 jonathan 746 eq(proj.GetParameter("ellps"), "clrk66")
605    
606 bh 1257 self.check_format()
607 bh 957
608 bh 1257
609 bh 957 class TestRasterLayer(LoadSessionTest):
610    
611     file_contents = '''\
612     <?xml version="1.0" encoding="UTF-8"?>
613 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
614 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
615 bh 1268 title="single map&amp;layer">
616     <map title="Test Map">
617     <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
618     title="My RasterLayer"/>
619 bh 957 </map>
620     </session>
621     '''
622    
623     def test(self):
624 jonathan 947 eq = self.assertEquals
625     neq = self.assertNotEqual
626    
627 bh 957 session = load_session(self.filename())
628 jonathan 947 self.session = session
629    
630     map = self.session.Maps()[0] # only one map in the sample
631    
632     layer = map.Layers()[0] # one layer in the sample
633    
634     eq(layer.Title(), "My RasterLayer")
635     self.failIf(layer.Visible())
636     self.failUnless(filenames_equal(layer.GetImageFilename(),
637     os.path.join(self.temp_dir(),
638     os.pardir, os.pardir,
639     "Data", "iceland",
640     "island.tif")))
641 bh 1257 self.check_format()
642 jonathan 947
643 bh 1268
644     class TestJoinedTable(LoadSessionTest):
645    
646     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
647 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
648 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd" title="A Joined Table session">
649 bh 1282 <fileshapesource filetype="shapefile" id="D137227612"
650     filename="../../Data/iceland/roads-line.shp"/>
651     <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
652     title="Some Title"/>
653 bh 1375 <jointable id="D136169900" title="Joined"
654     right="D136171140" left="D137227612"
655     leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
656     jointype="LEFT OUTER"/>
657 bh 1282 <derivedshapesource table="D136169900" shapesource="D137227612"
658     id="D136170932"/>
659 bh 1268 <map title="Test Map">
660 bh 1282 <layer shapestore="D136170932" visible="true" stroke="#000000"
661     title="My Layer" stroke_width="1" fill="None"/>
662 bh 1268 </map>
663 bh 1282 </session>
664     '''
665 bh 1268
666     def setUp(self):
667     """Extend inherited method to create the dbffile for the join"""
668     LoadSessionTest.setUp(self)
669     dbffile = self.temp_file_name("load_joinedtable.dbf")
670     dbf = dbflib.create(dbffile)
671     dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
672     dbf.add_field("TEXT", dbflib.FTString, 10, 0)
673     dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
674     dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
675     dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
676     dbf.close()
677    
678     def test(self):
679     """Test loading a session containing a joined table"""
680     session = load_session(self.filename())
681     self.session = session
682    
683     tables = session.Tables()
684     self.assertEquals(len(tables), 3)
685     # FIXME: The tests shouldn't assume a certain order of the tables
686     self.assertEquals(tables[0].Title(), "Some Title")
687     self.assertEquals(tables[1].Title(), "Joined")
688 bh 1375 self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
689 bh 1282 self.check_format()
690 bh 1268
691    
692 bh 2034 class TestLabelLayer(LoadSessionTest):
693 bh 1646
694 bh 2034 # Note that the labels deliberately contain non-ascii characters to
695     # test whether they're supported correctly.
696    
697     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
698     <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
699     <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd" title="Thuban sample session">
700     <fileshapesource filetype="shapefile" id="D145265052"
701     filename="../../Data/iceland/political.shp"/>
702     <fileshapesource filetype="shapefile" id="D145412868"
703     filename="../../Data/iceland/cultural_landmark-point.shp"/>
704     <map title="Iceland map">
705     <projection name="Unknown">
706     <parameter value="zone=26"/>
707     <parameter value="proj=utm"/>
708     <parameter value="ellps=clrk66"/>
709     </projection>
710     <layer shapestore="D145265052" visible="true" stroke="#000000"
711     title="political" stroke_width="1" fill="#c0c0c0">
712     <projection name="Geographic">
713     <parameter value="proj=latlong"/>
714     <parameter value="to_meter=0.017453"/>
715     <parameter value="ellps=clrk66"/>
716     </projection>
717     </layer>
718     <layer shapestore="D145412868" visible="true" stroke="#000000"
719     title="landmarks" stroke_width="1" fill="#ffff00">
720     <projection name="Geographic">
721     <parameter value="proj=latlong"/>
722     <parameter value="to_meter=0.017453"/>
723     <parameter value="ellps=clrk66"/>
724     </projection>
725     </layer>
726     <labellayer>
727     <label x="-21.5" y="64.25" text="RUINS"
728     halign="left" valign="center"/>
729     <label x="-15.125" y="64.75" text="H\xc3\xbctte"
730     halign="right" valign="top"/>
731     </labellayer>
732     </map>
733     </session>
734     '''
735    
736     def test(self):
737     """Test loading a session with a label layer"""
738     session = load_session(self.filename())
739     self.session = session
740    
741     label_layer = self.session.Maps()[0].LabelLayer()
742     expected_labels = [(-21.5, 64.25, "RUINS", ALIGN_LEFT, ALIGN_CENTER),
743     (-15.125, 64.75, "H\xfctte", ALIGN_RIGHT, ALIGN_TOP),
744     ]
745     for label, values in zip(label_layer.Labels(), expected_labels):
746     self.assertEquals((label.x, label.y, label.text, label.halign,
747     label.valign),
748     values)
749     self.check_format()
750    
751    
752 bh 1646 class TestPostGISLayer(LoadSessionTest):
753    
754     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
755 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
756 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
757 bh 1646 title="unnamed session">
758     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
759     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
760     <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
761     <map title="unnamed map">
762     <layer shapestore="D143149420" visible="true" stroke="#000000"
763     title="landmarks" stroke_width="1" fill="None"/>
764     </map>
765     </session>
766     '''
767    
768     def setUp(self):
769     """Extend the inherited method to start the postgis server
770    
771     Furthermore, patch the file contents with the real postgis db
772     information
773     """
774     postgissupport.skip_if_no_postgis()
775     self.server = postgissupport.get_test_server()
776     self.postgisdb = self.server.get_default_static_data_db()
777    
778     self.file_contents = self.__class__.file_contents % {
779     "dbname": self.postgisdb.dbname,
780     "user": self.server.user_name,
781     "port": self.server.port,
782     "host": self.server.host}
783     LoadSessionTest.setUp(self)
784    
785     def test(self):
786     """Test loading a session containing a postgis shapestore"""
787     session = load_session(self.filename())
788     self.session = session
789     connections = session.DBConnections()
790     self.assertEquals(len(connections), 1)
791     conn = connections[0]
792     for attr, value in [("host", self.server.host),
793     ("port", str(self.server.port)),
794     ("user", self.server.user_name),
795     ("dbname", self.postgisdb.dbname)]:
796     self.assertEquals(getattr(conn, attr), value)
797     layer = session.Maps()[0].Layers()[0]
798     self.failUnless(layer.ShapeStore().DBConnection() is conn)
799    
800    
801     class TestPostGISLayerPassword(LoadSessionTest):
802    
803     file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
804 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
805 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
806 bh 1646 title="unnamed session">
807     <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
808     dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
809     <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
810     <map title="unnamed map">
811     <layer shapestore="D143149420" visible="true" stroke="#000000"
812     title="landmarks" stroke_width="1" fill="None"/>
813     </map>
814     </session>
815     '''
816    
817     def setUp(self):
818     """Extend the inherited method to start the postgis server
819    
820     Furthermore, patch the file contents with the real postgis db
821     information
822     """
823     postgissupport.skip_if_no_postgis()
824     self.server = postgissupport.get_test_server()
825     self.postgisdb = self.server.get_default_static_data_db()
826    
827     self.file_contents = self.__class__.file_contents % {
828     "dbname": self.postgisdb.dbname,
829     "user": self.server.user_name,
830     "port": self.server.port,
831     "host": self.server.host}
832     LoadSessionTest.setUp(self)
833    
834     self.db_connection_callback_called = False
835     self.server.require_authentication(True)
836    
837     def tearDown(self):
838     """Extend the inherited method to switch off postgresql authentication
839     """
840     self.server.require_authentication(False)
841     LoadSessionTest.tearDown(self)
842    
843     def db_connection_callback(self, params, message):
844     """Implementation of Thuban.Model.hooks.query_db_connection_parameters
845     """
846     self.assertEquals(params,
847     {"dbname": self.postgisdb.dbname,
848     "user": self.server.user_name,
849     "port": str(self.server.port),
850     "host": self.server.host})
851     self.db_connection_callback_called = True
852     params = params.copy()
853     params["password"] = self.server.user_password
854     return params
855    
856     def test_with_callback(self):
857     """Test loading a session with postgis, authentication and a callback
858     """
859     session = load_session(self.filename(),
860     db_connection_callback = self.db_connection_callback)
861     self.session = session
862     connections = session.DBConnections()
863     self.assertEquals(len(connections), 1)
864     conn = connections[0]
865     for attr, value in [("host", self.server.host),
866     ("port", str(self.server.port)),
867     ("user", self.server.user_name),
868     ("dbname", self.postgisdb.dbname)]:
869     self.assertEquals(getattr(conn, attr), value)
870     layer = session.Maps()[0].Layers()[0]
871     self.failUnless(layer.ShapeStore().DBConnection() is conn)
872     self.failUnless(self.db_connection_callback_called)
873    
874     def test_without_callback(self):
875     """Test loading a session with postgis, authentication and no callback
876     """
877     # A password is required and there's no callback, so we should
878     # get a ConnectionError
879     self.assertRaises(ConnectionError, load_session, self.filename())
880    
881     def test_cancel(self):
882     """Test loading a session with postgis and cancelling authentication
883     """
884     def cancel(*args):
885     self.db_connection_callback_called = True
886     return None
887    
888     # If the user cancels, i.e. if the callbakc returns None, a
889     # LoadCancelled exception is raised.
890     self.assertRaises(LoadCancelled,
891     load_session, self.filename(), cancel)
892     self.failUnless(self.db_connection_callback_called)
893    
894    
895 bh 1268 class TestLoadError(LoadSessionTest):
896    
897     file_contents = '''\
898     <?xml version="1.0" encoding="UTF-8"?>
899 bh 1846 <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
900 bh 2004 <session xmlns="http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd"
901 bh 1268 title="single map&amp;layer">
902     <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
903     <map title="Test Map">
904     <projection name="Unknown">
905     <parameter value="zone=26"/>
906     <parameter value="proj=utm"/>
907     <parameter value="ellps=clrk66"/>
908     </projection>
909     <layer shapestore="D1" visible="true"
910     stroke="#000000" title="My Layer" stroke_width="1"
911     fill="None"/>
912     </map>
913     </session>
914     '''
915    
916     def test(self):
917     """Test loading a session missing a required attribute"""
918     # Don't use assertRaises to make sure that if a session is
919     # actually returned it gets destroyed properly.
920     try:
921     self.session = load_session(self.filename())
922     except LoadError, value:
923 bh 1642 # Check the actual messge in value to make sure the
924     # LoadError really was about the missing attribute
925     self.assertEquals(str(value),
926     "Element "
927 bh 2004 "(u'http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd',"
928 bh 1642 " u'fileshapesource') requires an attribute 'filetype'")
929 bh 1268 else:
930     self.fail("Missing filetype attribute doesn't raise LoadError")
931    
932 bh 292 if __name__ == "__main__":
933 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