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

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

Parent Directory Parent Directory | Revision Log Revision Log


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