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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1247  
changed lines
  Added in v.2642

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26