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

Legend:
Removed from v.1257  
changed lines
  Added in v.2620

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26