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

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

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

revision 1245 by bh, Thu Jun 19 19:29:23 2003 UTC revision 2552 by jonathan, Fri Jan 28 15:54:00 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 17  import os Line 17  import os
17  import unittest  import unittest
18  from StringIO import StringIO  from StringIO import StringIO
19    
 import xml.sax  
 import xml.sax.handler  
 from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException  
   
20  import xmlsupport  import xmlsupport
21    import postgissupport
22    
23  import support  import support
24  support.initthuban()  support.initthuban()
25    
26  from Thuban.Model.save import XMLWriter, save_session  import dbflib
27    
28    from Thuban.Lib.fileutil import relative_filename
29    from Thuban.Model.save import XMLWriter, save_session, sort_data_stores
30  from Thuban.Model.session import Session  from Thuban.Model.session import Session
31  from Thuban.Model.map import Map  from Thuban.Model.map import Map
32  from Thuban.Model.layer import Layer, RasterLayer  from Thuban.Model.layer import Layer, RasterLayer
33  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
34    from Thuban.Model.table import DBFTable
35    from Thuban.Model.transientdb import TransientJoinedTable
36    from Thuban.Model.data import DerivedShapeStore
37    
38  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
39      ClassGroupProperties      ClassGroupProperties
40    
41  from Thuban.Model.range import Range  from Thuban.Model.range import Range
42    
43    from Thuban.Model.postgisdb import PostGISConnection, PostGISShapeStore
44    
 class SaxEventLister(xml.sax.handler.ContentHandler):  
   
     def __init__(self):  
         self.eventlist = []  
   
     def startElementNS(self, name, qname, attrs):  
         items = attrs.items()  
         items.sort()  
         self.eventlist.append(("start", name, qname, items))  
   
     def endElementNS(self, name, qname):  
         self.eventlist.append(("end", name, qname))  
   
   
 def sax_eventlist(data):  
     """Return a list of SAX event generated for the XML data.  
     """  
     handler = SaxEventLister()  
     parser = make_parser()  
     parser.setContentHandler(handler)  
     parser.setErrorHandler(ErrorHandler())  
     parser.setFeature(xml.sax.handler.feature_namespaces, 1)  
   
     #  
     # see comment at the end of Thuban/Model/load.py  
     #  
     try:  
         parser.setFeature(xml.sax.handler.feature_validation, 0)  
         parser.setFeature(xml.sax.handler.feature_external_ges, 0)  
         parser.setFeature(xml.sax.handler.feature_external_pes, 0)  
     except SAXNotRecognizedException:  
         pass  
   
     inpsrc = xml.sax.InputSource()  
     inpsrc.setByteStream(StringIO(data))  
     parser.parse(inpsrc)  
   
     return handler.eventlist  
45    
46  class XMLWriterTest(unittest.TestCase):  class XMLWriterTest(unittest.TestCase):
47    
# Line 99  class XMLWriterTest(unittest.TestCase): Line 65  class XMLWriterTest(unittest.TestCase):
65  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
66                        xmlsupport.ValidationTest):                        xmlsupport.ValidationTest):
67    
68        dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
69        thubanids = [((dtd, n), (None, "id")) for n in
70                     ["fileshapesource", "filetable", "jointable",
71                      "derivedshapesource", "dbshapesource", "dbconnection"]]
72        thubanidrefs = [((dtd, n), (None, m)) for n, m in
73                        [("layer", "shapestore"),
74                         ("jointable", "left"),
75                         ("jointable", "right"),
76                         ("derivedshapesource", "table"),
77                         ("derivedshapesource", "shapesource"),
78                         ("dbshapesource", "dbconn")]]
79        del n, m, dtd
80    
81        def tearDown(self):
82            """Call self.session.Destroy
83    
84            Test cases that create session should bind it to self.session so
85            that it gets destroyed properly
86            """
87            if hasattr(self, "session"):
88                self.session.Destroy()
89                self.session = None
90    
91      def compare_xml(self, xml1, xml2):      def compare_xml(self, xml1, xml2):
92          self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))          list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
93                                             idrefs = self.thubanidrefs)
94            list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
95                                             idrefs = self.thubanidrefs)
96            if list1 != list2:
97                for a, b in zip(list1, list2):
98                    if a != b:
99                        self.fail("%r != %r" % (a, b))
100    
101    
102      def testEmptySession(self):      def testEmptySession(self):
103          """Save an empty session"""          """Save an empty session"""
# Line 114  class SaveSessionTest(unittest.TestCase, Line 111  class SaveSessionTest(unittest.TestCase,
111          file.close()          file.close()
112          self.compare_xml(written_contents,          self.compare_xml(written_contents,
113                           '<?xml version="1.0" encoding="UTF-8"?>\n'                           '<?xml version="1.0" encoding="UTF-8"?>\n'
114                           '<!DOCTYPE session SYSTEM "thuban.dtd">\n'                           '<!DOCTYPE session SYSTEM "thuban-1.1.dtd">\n'
115                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
116             'xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">'
117                             '\n</session>\n')
118    
119          self.validate_data(written_contents)          self.validate_data(written_contents)
120    
# Line 123  class SaveSessionTest(unittest.TestCase, Line 122  class SaveSessionTest(unittest.TestCase,
122          """Save a session with a single map with a single layer"""          """Save a session with a single map with a single layer"""
123          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
124          session = Session("single map&layer")          session = Session("single map&layer")
125          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["proj=utm", "zone=27", "ellps=WGS84",
126                               "datum=WGS84", "units=m"],
127                              name = "WGS 84 / UTM zone 27N",
128                              epsg = "32627")
129          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
130          session.AddMap(map)          session.AddMap(map)
131          # use shapefile from the example data          # use shapefile from the example data
# Line 139  class SaveSessionTest(unittest.TestCase, Line 141  class SaveSessionTest(unittest.TestCase,
141          written_contents = file.read()          written_contents = file.read()
142          file.close()          file.close()
143          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
144          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
145          <session title="single map&amp;layer">          <session title="single map&amp;layer"
146               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
147                <fileshapesource id="D1"
148                    filename="../../Data/iceland/political.shp"
149                    filetype="shapefile"/>
150              <map title="Test Map">              <map title="Test Map">
151                  <projection name="Unknown">                  <projection epsg="32627" name="WGS 84 / UTM zone 27N">
                     <parameter value="zone=26"/>  
152                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
153                      <parameter value="ellps=clrk66"/>                      <parameter value="zone=27"/>
154                        <parameter value="ellps=WGS84"/>
155                        <parameter value="datum=WGS84"/>
156                        <parameter value="units=m"/>
157                  </projection>                  </projection>
158                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
159                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
160              </map>              </map>
161          </session>'''          </session>'''
162            
163          expected_contents = expected_template % \          expected_contents = expected_template % "true"
             (os.path.join("..", "..", "Data", "iceland", "political.shp"),  
              "true")  
164    
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
165          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
166    
167          self.validate_data(written_contents)          self.validate_data(written_contents)
168    
169            # Repeat with an invisible layer
170          layer.SetVisible(False)          layer.SetVisible(False)
171          save_session(session, filename)          save_session(session, filename)
172    
173          file = open(filename)          file = open(filename)
174          written_contents = file.read()          written_contents = file.read()
175          file.close()          file.close()
176          expected_contents = expected_template % \          expected_contents = expected_template % "false"
             (os.path.join("..", "..", "Data", "iceland", "political.shp"),  
              "false")  
   
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
177          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
178          self.validate_data(written_contents)          self.validate_data(written_contents)
179    
180          session.Destroy()          session.Destroy()
181    
182      def testLayerProjection(self):      def testLayerProjection(self):
183            """Test saving layers with projections"""
184          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
185          session = Session("single map&layer")          session = self.session = Session("single map&layer")
186          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
187          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
188          session.AddMap(map)          session.AddMap(map)
# Line 191  class SaveSessionTest(unittest.TestCase, Line 190  class SaveSessionTest(unittest.TestCase,
190          shpfile = os.path.join(os.path.dirname(__file__),          shpfile = os.path.join(os.path.dirname(__file__),
191                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
192          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
193          proj = Projection(["proj=lcc", "ellps=clrk66"], "Layer Projection")          proj = Projection(["proj=lcc", "ellps=clrk66",
194                               "lat_1=0", "lat_2=20"],
195                              "Layer Projection")
196          layer.SetProjection(proj)          layer.SetProjection(proj)
197          map.AddLayer(layer)          map.AddLayer(layer)
198    
199          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
200          save_session(session, filename)          save_session(session, filename)
         session.Destroy()  
201    
202          file = open(filename)          file = open(filename)
203          written_contents = file.read()          written_contents = file.read()
204          file.close()          file.close()
205          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
206          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
207          <session title="single map&amp;layer">          <session title="single map&amp;layer"
208               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
209                <fileshapesource id="D1"
210                    filename="../../Data/iceland/political.shp"
211                    filetype="shapefile"/>
212              <map title="Test Map">              <map title="Test Map">
213                  <projection name="Unknown">                  <projection name="Unknown">
214                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
215                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
216                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
217                  </projection>                  </projection>
218                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
219                  fill="None" stroke="#000000" stroke_width="1" visible="true">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
220                      <projection name="Layer Projection">                      <projection name="Layer Projection">
221                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
222                          <parameter value="ellps=clrk66"/>                          <parameter value="ellps=clrk66"/>
223                            <parameter value="lat_1=0"/>
224                            <parameter value="lat_2=20"/>
225                      </projection>                      </projection>
226                  </layer>                  </layer>
227              </map>              </map>
228          </session>''' % os.path.join("..", "..", "Data", "iceland",          </session>'''
                                      "political.shp")  
229          #print written_contents          #print written_contents
230          #print "********************************************"          #print "********************************************"
231          #print expected_contents          #print expected_contents
# Line 239  class SaveSessionTest(unittest.TestCase, Line 244  class SaveSessionTest(unittest.TestCase,
244          layer = RasterLayer("My RasterLayer", imgfile)          layer = RasterLayer("My RasterLayer", imgfile)
245          map.AddLayer(layer)          map.AddLayer(layer)
246    
247          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("%s.thuban" % self.id())
248          save_session(session, filename)          save_session(session, filename)
249          session.Destroy()          session.Destroy()
250    
# Line 247  class SaveSessionTest(unittest.TestCase, Line 252  class SaveSessionTest(unittest.TestCase,
252          written_contents = file.read()          written_contents = file.read()
253          file.close()          file.close()
254          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
255          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
256          <session title="single map&amp;layer">          <session title="single map&amp;layer"
257               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
258              <map title="Test Map">              <map title="Test Map">
259                  <rasterlayer title="My RasterLayer" filename="%s"                  <rasterlayer title="My RasterLayer"
260                               visible="true">                          filename="../../Data/iceland/island.tif"
261                            visible="true">
262                  </rasterlayer>                  </rasterlayer>
263              </map>              </map>
264          </session>''' % os.path.join(os.path.dirname(__file__),          </session>'''
                                      os.pardir, "Data", "iceland",  
                                      "island.tif")  
265          #print written_contents          #print written_contents
266          #print "********************************************"          #print "********************************************"
267          #print expected_contents          #print expected_contents
# Line 265  class SaveSessionTest(unittest.TestCase, Line 270  class SaveSessionTest(unittest.TestCase,
270          self.validate_data(written_contents)          self.validate_data(written_contents)
271    
272      def testClassifiedLayer(self):      def testClassifiedLayer(self):
273          """Save a session with a single map with a single layer          """Save a session with a single map with classifications"""
            with a classificaton.  
         """  
274          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
275          session = Session("single map&layer")          session = Session("Map with Classifications")
276          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
277          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
278          session.AddMap(map)          session.AddMap(map)
# Line 278  class SaveSessionTest(unittest.TestCase, Line 281  class SaveSessionTest(unittest.TestCase,
281                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
282          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
283          map.AddLayer(layer)          map.AddLayer(layer)
284            layer2 = Layer("My Layer", layer.ShapeStore())
285            map.AddLayer(layer2)
286    
287          clazz = layer.GetClassification()          clazz = layer.GetClassification()
288    
289          clazz.SetField("AREA")          layer.SetClassificationColumn("AREA")
290    
291          clazz.AppendGroup(ClassGroupSingleton(42,          clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
292                                             ClassGroupProperties(),                                                "single"))
293                                             "single"))          clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
294          clazz.AppendGroup(ClassGroupSingleton("text",                                                "single-text"))
                                            ClassGroupProperties(),  
                                            "single-text"))  
295    
296          clazz.AppendGroup(ClassGroupRange(0, 42,          clazz.AppendGroup(ClassGroupRange((0, 42),
297                                             ClassGroupProperties(),                                             ClassGroupProperties(),
298                                             "range"))                                             "range"))
299    
# Line 299  class SaveSessionTest(unittest.TestCase, Line 302  class SaveSessionTest(unittest.TestCase,
302          range.SetLabel("new-range")          range.SetLabel("new-range")
303          clazz.AppendGroup(range)          clazz.AppendGroup(range)
304    
305          filename = self.temp_file_name("save_singlemap.thuban")  
306            clazz = layer2.GetClassification()
307            layer2.SetClassificationColumn("POPYCOUN")
308    
309            # Classification with Latin 1 text
310            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
311                                                  ClassGroupProperties(),
312                                                  '\xdcml\xe4uts')) # Uemlaeuts
313    
314    
315            filename = self.temp_file_name("%s.thuban" % self.id())
316          save_session(session, filename)          save_session(session, filename)
317    
318          file = open(filename)          file = open(filename)
319          written_contents = file.read()          written_contents = file.read()
320          file.close()          file.close()
321          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
322          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
323          <session title="single map&amp;layer">          <session title="Map with Classifications"
324               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
325                <fileshapesource id="D1"
326                    filename="../../Data/iceland/political.shp"
327                    filetype="shapefile"/>
328              <map title="Test Map">              <map title="Test Map">
329                  <projection name="Unknown">                  <projection name="Unknown">
330                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
331                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
332                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
333                  </projection>                  </projection>
334                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
335                  fill="None" stroke="#000000" stroke_width="1" visible="%s">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
336                      <classification field="AREA" field_type="double">                      <classification field="AREA" field_type="double">
337                          <clnull label="">                          <clnull label="">
338                              <cldata fill="None" stroke="#000000" stroke_width="1"/>                              <cldata fill="None" stroke="#000000" stroke_width="1"/>
# Line 334  class SaveSessionTest(unittest.TestCase, Line 351  class SaveSessionTest(unittest.TestCase,
351                          </clrange>                          </clrange>
352                      </classification>                      </classification>
353                  </layer>                  </layer>
354                    <layer title="My Layer" shapestore="D1"
355                    fill="None" stroke="#000000" stroke_width="1" visible="true">
356                        <classification field="POPYCOUN" field_type="string">
357                            <clnull label="">
358                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
359                            </clnull>
360                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
361                                 label="\xc3\x9cml\xc3\xa4uts">
362                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
363                            </clpoint>
364                        </classification>
365                    </layer>
366              </map>              </map>
367          </session>'''          </session>'''
368    
         expected_contents = expected_template % \  
             (os.path.join("..", "..", "Data", "iceland", "political.shp"),  
              "true")  
   
369          #print written_contents          #print written_contents
370          #print "********************************************"          #print "********************************************"
371          #print expected_contents          #print expected_contents
# Line 350  class SaveSessionTest(unittest.TestCase, Line 375  class SaveSessionTest(unittest.TestCase,
375    
376          session.Destroy()          session.Destroy()
377    
378        def test_dbf_table(self):
379            """Test saving a session with a dbf table link"""
380            session = self.session = Session("a DBF Table session")
381            # use shapefile from the example data
382            dbffile = os.path.join(os.path.dirname(__file__),
383                                   os.pardir, "Data", "iceland", "political.dbf")
384            table = session.AddTable(DBFTable(dbffile))
385    
386            filename = self.temp_file_name("save_singletable.thuban")
387            save_session(session, filename)
388    
389            file = open(filename)
390            written_contents = file.read()
391            file.close()
392            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
393            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
394            <session title="a DBF Table session"
395               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
396                <filetable id="D1" filename="../../Data/iceland/political.dbf"
397                    filetype="DBF" title="political"/>
398            </session>'''
399    
400            self.compare_xml(written_contents, expected_contents)
401            self.validate_data(written_contents)
402    
403        def test_joined_table(self):
404            """Test saving a session with joined table"""
405            # Create a simple table to use in the join
406            dbffile = self.temp_file_name("save_joinedtable.dbf")
407            dbf = dbflib.create(dbffile)
408            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
409            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
410            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
411            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
412            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
413            dbf.close()
414    
415            # Create the session and a map
416            session = Session("A Joined Table session")
417            try:
418                map = Map("Test Map")
419                session.AddMap(map)
420    
421                # Add the dbf file to the session
422                dbftable = session.AddTable(DBFTable(dbffile))
423    
424                # Create a layer with the shapefile to use in the join
425                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
426                                       os.pardir, "Data", "iceland",
427                                       "roads-line.shp")
428                layer = Layer("My Layer", session.OpenShapefile(shpfile))
429                map.AddLayer(layer)
430    
431                # Do the join
432                store = layer.ShapeStore()
433                #for col in store.Table().Columns():
434                #    print col.name
435                joined = TransientJoinedTable(session.TransientDB(),
436                                              store.Table(), "RDLNTYPE",
437                                              dbftable, "RDTYPE",
438                                              outer_join = True)
439                store = session.AddShapeStore(DerivedShapeStore(store, joined))
440                layer.SetShapeStore(store)
441    
442                # Save the session
443                filename = self.temp_file_name("save_joinedtable.thuban")
444                save_session(session, filename)
445    
446                # Read it back and compare
447                file = open(filename)
448                written_contents = file.read()
449                file.close()
450                expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
451                <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
452                <session title="A Joined Table session"
453                 xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
454                    <fileshapesource filename="../../Data/iceland/roads-line.shp"
455                                     filetype="shapefile" id="D142197204"/>
456                    <filetable filename="save_joinedtable.dbf"
457                               title="save_joinedtable"
458                               filetype="DBF" id="D141881756"/>
459                    <jointable id="D142180284"
460                               title="Join of roads-line and save_joinedtable"
461                               leftcolumn="RDLNTYPE" left="D142197204"
462                               rightcolumn="RDTYPE" right="D141881756"
463                               jointype="LEFT OUTER" />
464                    <derivedshapesource id="D141915644"
465                                        table="D142180284"
466                                        shapesource="D142197204"/>
467                    <map title="Test Map">
468                        <layer title="My Layer"
469                               shapestore="D141915644" visible="true"
470                               stroke="#000000" stroke_width="1" fill="None"/>
471                    </map>
472                </session>'''
473    
474                self.compare_xml(written_contents, expected_contents)
475                self.validate_data(written_contents)
476            finally:
477                session.Destroy()
478                session = None
479    
480    
481        def test_save_postgis(self):
482            """Test saving a session with a postgis connection"""
483    
484            class NonConnection(PostGISConnection):
485                """connection class that doesn't actually connect """
486                def connect(self):
487                    pass
488    
489            class NonConnectionStore(PostGISShapeStore):
490                """Shapestore that doesn't try to access the server"""
491                def _fetch_table_information(self):
492                    # pretend that we've found a geometry column
493                    self.geometry_column = "the_geom"
494                def IDColumn(self):
495                    """Return an object with a name attribute with value 'gid'"""
496                    class dummycol:
497                        name = "gid"
498                    return dummycol
499    
500            session = Session("A PostGIS Session")
501            try:
502                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
503                                       user="grue")
504                session.AddDBConnection(dbconn)
505                map = Map("Test Map")
506                session.AddMap(map)
507                store = NonConnectionStore(dbconn, "roads")
508                session.AddShapeStore(store)
509                layer = Layer("Roads to Nowhere", store)
510                map.AddLayer(layer)
511    
512                # Save the session
513                filename = self.temp_file_name(self.id() + ".thuban")
514                save_session(session, filename)
515    
516                # Read it back and compare
517                file = open(filename)
518                written = file.read()
519                file.close()
520                expected = '''<?xml version="1.0" encoding="UTF-8"?>
521                <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
522                <session title="A PostGIS Session"
523                 xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
524                    <dbconnection id="DB"
525                                  dbtype="postgis" dbname="plugh"
526                                  host="xyzzy" port="42"
527                                  user="grue"/>
528                    <dbshapesource id="roads" dbconn="DB" tablename="roads"
529                                   id_column="gid" geometry_column="the_geom"/>
530                    <map title="Test Map">
531                        <layer title="Roads to Nowhere"
532                               shapestore="roads" visible="true"
533                               stroke="#000000" stroke_width="1" fill="None"/>
534                    </map>
535                </session>'''
536                self.compare_xml(written, expected)
537                self.validate_data(written)
538            finally:
539                session.Destroy()
540    
541    
542    class MockDataStore:
543    
544        """A very simple data store that only has dependencies"""
545    
546        def __init__(self, name, *dependencies):
547            self.name = name
548            self.dependencies = dependencies
549    
550        def __repr__(self):
551            return self.name
552    
553        def Dependencies(self):
554            return self.dependencies
555    
556    
557    class TestStoreSort(unittest.TestCase):
558    
559        def check_sort(self, containers, sorted):
560            """Check whether the list of data containers is sorted"""
561            # check whether sorted is in the right order
562            seen = {}
563            for container in sorted:
564                self.failIf(id(container) in seen,
565                            "Container %r at least twice in %r" % (container,
566                                                                   sorted))
567                for dep in container.Dependencies():
568                    self.assert_(id(dep) in seen,
569                                 "Dependency %r of %r not yet seen" % (dep,
570                                                                       container))
571                seen[id(container)] = 1
572            # check whether all of containers is in sorted
573            for container in containers:
574                self.assert_(id(container) in seen,
575                             "Container %r in containers but not in sorted")
576            self.assertEquals(len(containers), len(sorted))
577    
578        def test_sort_data_stores(self):
579            """Test Thuban.Model.save.sort_data_stores"""
580            d1 = MockDataStore("d1")
581            d2 = MockDataStore("d2")
582            d3 = MockDataStore("d3", d1)
583            d4 = MockDataStore("d4", d1, d3)
584    
585            containers = [d4, d1, d2, d3]
586            self.check_sort(containers, sort_data_stores(containers))
587            containers = [d1, d3, d2, d4]
588            self.check_sort(containers, sort_data_stores(containers))
589    
590    
591    
592  if __name__ == "__main__":  if __name__ == "__main__":
593      # Fake the __file__ global because it's needed by a test      # Fake the __file__ global because it's needed by a test

Legend:
Removed from v.1245  
changed lines
  Added in v.2552

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26