/[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 1173 by jonathan, Thu Jun 12 13:37:18 2003 UTC revision 1664 by bh, Wed Aug 27 15:20:54 2003 UTC
# Line 17  import os Line 17  import os
17  import unittest  import unittest
18  from StringIO import StringIO  from StringIO import StringIO
19    
20  import xml.sax  import xmlsupport
21  import xml.sax.handler  import postgissupport
 from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException  
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    
48      def testEncode(self):      def testEncode(self):
49          """Test XMLWriter.encode"""          """Test XMLWriter.encode"""
50          writer = XMLWriter()          writer = XMLWriter()
51            eq = self.assertEquals
52    
53          writer.encode("hello world")          eq(writer.encode("hello world"), "hello world")
54          writer.encode(unicode("hello world"))          eq(writer.encode(unicode("hello world")), unicode("hello world"))
55    
56          writer.encode("\x80\x90\xc2\x100")          eq(writer.encode("\x80\x90\xc2\x100"),
57          writer.encode(u"\x80\x90\xc2\x100")                           "\xc2\x80\xc2\x90\xc3\x82\x100")
58          writer.encode(u"\xFF5E")          eq(writer.encode(u"\x80\x90\xc2\x100"),
59                             "\xc2\x80\xc2\x90\xc3\x82\x100")
60          self.assertEquals(writer.encode('&"\'<>'),          eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
61                            "&amp;&quot;&apos;&lt;&gt;")  
62          self.assertEquals(writer.encode(unicode('&"\'<>')),          eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
63                            "&amp;&quot;&apos;&lt;&gt;")          eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
64    
65  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
66                          xmlsupport.ValidationTest):
67    
68        dtd = "http://thuban.intevation.org/dtds/thuban-0.9.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 compare_xml(self, xml1, xml2):      def compare_xml(self, xml1, xml2):
82          self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))          list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
83                                             idrefs = self.thubanidrefs)
84            list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
85                                             idrefs = self.thubanidrefs)
86            if list1 != list2:
87                for a, b in zip(list1, list2):
88                    if a != b:
89                        self.fail("%r != %r" % (a, b))
90    
91    
92      def testEmptySession(self):      def testEmptySession(self):
93          """Save an empty session"""          """Save an empty session"""
# Line 110  class SaveSessionTest(unittest.TestCase, Line 101  class SaveSessionTest(unittest.TestCase,
101          file.close()          file.close()
102          self.compare_xml(written_contents,          self.compare_xml(written_contents,
103                           '<?xml version="1.0" encoding="UTF-8"?>\n'                           '<?xml version="1.0" encoding="UTF-8"?>\n'
104                           '<!DOCTYPE session SYSTEM "thuban.dtd">\n'                           '<!DOCTYPE session SYSTEM "thuban-0.9.dtd">\n'
105                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
106             'xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">'
107                             '\n</session>\n')
108    
109            self.validate_data(written_contents)
110    
111      def testSingleLayer(self):      def testSingleLayer(self):
112          """Save a session with a single map with a single layer"""          """Save a session with a single map with a single layer"""
# Line 133  class SaveSessionTest(unittest.TestCase, Line 128  class SaveSessionTest(unittest.TestCase,
128          written_contents = file.read()          written_contents = file.read()
129          file.close()          file.close()
130          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
131          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
132          <session title="single map&amp;layer">          <session title="single map&amp;layer"
133               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
134                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
135              <map title="Test Map">              <map title="Test Map">
136                  <projection name="Unknown">                  <projection name="Unknown">
137                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
138                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
139                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
140                  </projection>                  </projection>
141                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
142                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
143              </map>              </map>
144          </session>'''          </session>'''
145            
146          expected_contents = expected_template % \          expected_contents = expected_template % \
147              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
148               "true")               "true")
149    
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
150          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
151    
152            self.validate_data(written_contents)
153    
154          layer.SetVisible(False)          layer.SetVisible(False)
155          save_session(session, filename)          save_session(session, filename)
156    
# Line 164  class SaveSessionTest(unittest.TestCase, Line 160  class SaveSessionTest(unittest.TestCase,
160          expected_contents = expected_template % \          expected_contents = expected_template % \
161              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
162               "false")               "false")
   
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
163          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
164            self.validate_data(written_contents)
165    
166          session.Destroy()          session.Destroy()
167    
168      def testLayerProjection(self):      def testLayerProjection(self):
169            """Test saving layers with projections"""
170          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
171          session = Session("single map&layer")          session = Session("single map&layer")
172          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
# Line 186  class SaveSessionTest(unittest.TestCase, Line 180  class SaveSessionTest(unittest.TestCase,
180          layer.SetProjection(proj)          layer.SetProjection(proj)
181          map.AddLayer(layer)          map.AddLayer(layer)
182    
183          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
184          save_session(session, filename)          save_session(session, filename)
185          session.Destroy()          session.Destroy()
186    
# Line 194  class SaveSessionTest(unittest.TestCase, Line 188  class SaveSessionTest(unittest.TestCase,
188          written_contents = file.read()          written_contents = file.read()
189          file.close()          file.close()
190          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
191          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
192          <session title="single map&amp;layer">          <session title="single map&amp;layer"
193               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
194                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
195              <map title="Test Map">              <map title="Test Map">
196                  <projection name="Unknown">                  <projection name="Unknown">
197                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
198                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
199                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
200                  </projection>                  </projection>
201                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
202                  fill="None" stroke="#000000" stroke_width="1" visible="true">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
203                      <projection name="Layer Projection">                      <projection name="Layer Projection">
204                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
# Line 217  class SaveSessionTest(unittest.TestCase, Line 213  class SaveSessionTest(unittest.TestCase,
213          #print expected_contents          #print expected_contents
214          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
215    
216                    self.validate_data(written_contents)
217    
218      def testRasterLayer(self):      def testRasterLayer(self):
219          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
220          session = Session("single map&layer")          session = Session("single map&layer")
# Line 228  class SaveSessionTest(unittest.TestCase, Line 225  class SaveSessionTest(unittest.TestCase,
225                                 os.pardir, "Data", "iceland", "island.tif")                                 os.pardir, "Data", "iceland", "island.tif")
226          layer = RasterLayer("My RasterLayer", imgfile)          layer = RasterLayer("My RasterLayer", imgfile)
227          map.AddLayer(layer)          map.AddLayer(layer)
228                                                                                    
229          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("%s.thuban" % self.id())
230          save_session(session, filename)          save_session(session, filename)
231          session.Destroy()          session.Destroy()
232                                                                                    
233          file = open(filename)          file = open(filename)
234          written_contents = file.read()          written_contents = file.read()
235          file.close()          file.close()
236          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
237          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
238          <session title="single map&amp;layer">          <session title="single map&amp;layer"
239               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
240              <map title="Test Map">              <map title="Test Map">
241                  <rasterlayer title="My RasterLayer" filename="%s"                  <rasterlayer title="My RasterLayer" filename="%s"
242                               visible="true">                               visible="true">
243                  </rasterlayer>                  </rasterlayer>
244              </map>              </map>
245          </session>''' % os.path.join(os.path.dirname(__file__),          </session>''' % os.path.join(os.pardir, os.pardir, "Data", "iceland",
                                      os.pardir, "Data", "iceland",  
246                                       "island.tif")                                       "island.tif")
247          #print written_contents          #print written_contents
248          #print "********************************************"          #print "********************************************"
249          #print expected_contents          #print expected_contents
250          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
251    
252            self.validate_data(written_contents)
253    
254      def testClassifiedLayer(self):      def testClassifiedLayer(self):
255          """Save a session with a single map with a single layer          """Save a session with a single map with classifications"""
            with a classificaton.  
         """  
256          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
257          session = Session("single map&layer")          session = Session("Map with Classifications")
258          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
259          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
260          session.AddMap(map)          session.AddMap(map)
# Line 266  class SaveSessionTest(unittest.TestCase, Line 263  class SaveSessionTest(unittest.TestCase,
263                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
264          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
265          map.AddLayer(layer)          map.AddLayer(layer)
266            layer2 = Layer("My Layer", layer.ShapeStore())
267            map.AddLayer(layer2)
268    
269          clazz = layer.GetClassification()          clazz = layer.GetClassification()
270    
271          clazz.SetField("AREA")          layer.SetClassificationColumn("AREA")
272    
273          clazz.AppendGroup(ClassGroupSingleton(42,          clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
274                                             ClassGroupProperties(),                                                "single"))
275                                             "single"))          clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
276          clazz.AppendGroup(ClassGroupSingleton("text",                                                "single-text"))
                                            ClassGroupProperties(),  
                                            "single-text"))  
277    
278          clazz.AppendGroup(ClassGroupRange(0, 42,          clazz.AppendGroup(ClassGroupRange((0, 42),
279                                             ClassGroupProperties(),                                             ClassGroupProperties(),
280                                             "range"))                                             "range"))
281    
# Line 287  class SaveSessionTest(unittest.TestCase, Line 284  class SaveSessionTest(unittest.TestCase,
284          range.SetLabel("new-range")          range.SetLabel("new-range")
285          clazz.AppendGroup(range)          clazz.AppendGroup(range)
286    
287          filename = self.temp_file_name("save_singlemap.thuban")  
288            clazz = layer2.GetClassification()
289            layer2.SetClassificationColumn("POPYCOUN")
290    
291            # Classification with Latin 1 text
292            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
293                                                  ClassGroupProperties(),
294                                                  '\xdcml\xe4uts')) # Uemlaeuts
295    
296    
297            filename = self.temp_file_name("%s.thuban" % self.id())
298          save_session(session, filename)          save_session(session, filename)
299    
300          file = open(filename)          file = open(filename)
301          written_contents = file.read()          written_contents = file.read()
302          file.close()          file.close()
303          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
304          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
305          <session title="single map&amp;layer">          <session title="Map with Classifications"
306               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
307                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
308              <map title="Test Map">              <map title="Test Map">
309                  <projection name="Unknown">                  <projection name="Unknown">
310                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
311                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
312                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
313                  </projection>                  </projection>
314                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
315                  fill="None" stroke="#000000" stroke_width="1" visible="%s">                  fill="None" stroke="#000000" stroke_width="1" visible="%s">
316                      <classification field="AREA" field_type="double">                      <classification field="AREA" field_type="double">
317                          <clnull label="">                          <clnull label="">
# Line 322  class SaveSessionTest(unittest.TestCase, Line 331  class SaveSessionTest(unittest.TestCase,
331                          </clrange>                          </clrange>
332                      </classification>                      </classification>
333                  </layer>                  </layer>
334                    <layer title="My Layer" shapestore="D1"
335                    fill="None" stroke="#000000" stroke_width="1" visible="true">
336                        <classification field="POPYCOUN" field_type="string">
337                            <clnull label="">
338                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
339                            </clnull>
340                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
341                                 label="\xc3\x9cml\xc3\xa4uts">
342                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
343                            </clpoint>
344                        </classification>
345                    </layer>
346              </map>              </map>
347          </session>'''          </session>'''
348            
349          expected_contents = expected_template % \          expected_contents = expected_template % \
350              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
351               "true")               "true")
# Line 334  class SaveSessionTest(unittest.TestCase, Line 355  class SaveSessionTest(unittest.TestCase,
355          #print expected_contents          #print expected_contents
356          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
357    
358            self.validate_data(written_contents)
359    
360          session.Destroy()          session.Destroy()
361    
362        def test_dbf_table(self):
363            """Test saving a session with a dbf table link"""
364            session = Session("a DBF Table session")
365            # use shapefile from the example data
366            dbffile = os.path.join(os.path.dirname(__file__),
367                                   os.pardir, "Data", "iceland", "political.dbf")
368            table = session.AddTable(DBFTable(dbffile))
369    
370            filename = self.temp_file_name("save_singletable.thuban")
371            save_session(session, filename)
372    
373            file = open(filename)
374            written_contents = file.read()
375            file.close()
376            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
377            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
378            <session title="a DBF Table session"
379               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
380                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
381            </session>'''
382    
383            expected_contents = (expected_template
384                                 % os.path.join(os.pardir, os.pardir, "Data",
385                                                "iceland", "political.dbf"))
386            self.compare_xml(written_contents, expected_contents)
387            self.validate_data(written_contents)
388    
389        def test_joined_table(self):
390            """Test saving a session with joined table"""
391            # Create a simple table to use in the join
392            dbffile = self.temp_file_name("save_joinedtable.dbf")
393            dbf = dbflib.create(dbffile)
394            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
395            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
396            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
397            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
398            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
399            dbf.close()
400    
401            # Create the session and a map
402            session = Session("A Joined Table session")
403            try:
404                map = Map("Test Map")
405                session.AddMap(map)
406    
407                # Add the dbf file to the session
408                dbftable = session.AddTable(DBFTable(dbffile))
409    
410                # Create a layer with the shapefile to use in the join
411                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
412                                       os.pardir, "Data", "iceland",
413                                       "roads-line.shp")
414                layer = Layer("My Layer", session.OpenShapefile(shpfile))
415                map.AddLayer(layer)
416    
417                # Do the join
418                store = layer.ShapeStore()
419                #for col in store.Table().Columns():
420                #    print col.name
421                joined = TransientJoinedTable(session.TransientDB(),
422                                              store.Table(), "RDLNTYPE",
423                                              dbftable, "RDTYPE",
424                                              outer_join = True)
425                store = session.AddShapeStore(DerivedShapeStore(store, joined))
426                layer.SetShapeStore(store)
427    
428                # Save the session
429                filename = self.temp_file_name("save_joinedtable.thuban")
430                save_session(session, filename)
431    
432                # Read it back and compare
433                file = open(filename)
434                written_contents = file.read()
435                file.close()
436                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
437                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
438                <session title="A Joined Table session"
439                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
440                    <fileshapesource filename="%(shpfile)s"
441                                     filetype="shapefile" id="D142197204"/>
442                    <filetable filename="%(dbffile)s"
443                               title="save_joinedtable"
444                               filetype="DBF" id="D141881756"/>
445                    <jointable id="D142180284"
446                               title="Join of roads-line and save_joinedtable"
447                               leftcolumn="RDLNTYPE" left="D142197204"
448                               rightcolumn="RDTYPE" right="D141881756"
449                               jointype="LEFT OUTER" />
450                    <derivedshapesource id="D141915644"
451                                        table="D142180284"
452                                        shapesource="D142197204"/>
453                    <map title="Test Map">
454                        <layer title="My Layer"
455                               shapestore="D141915644" visible="true"
456                               stroke="#000000" stroke_width="1" fill="None"/>
457                    </map>
458                </session>'''
459    
460                expected_contents = expected_template % {
461                    "dbffile": relative_filename(self.temp_dir(), dbffile),
462                    "shpfile": relative_filename(self.temp_dir(), shpfile)
463                    }
464                self.compare_xml(written_contents, expected_contents)
465                self.validate_data(written_contents)
466            finally:
467                session.Destroy()
468                session = None
469    
470    
471        def test_save_postgis(self):
472            """Test saving a session with a postgis connection"""
473    
474            class NonConnection(PostGISConnection):
475                """connection class that doesn't actually connect """
476                def connect(self):
477                    pass
478    
479            class NonConnectionStore(PostGISShapeStore):
480                """Shapestore that doesn't try to access the server"""
481                def _fetch_table_information(self):
482                    pass
483    
484            session = Session("A PostGIS Session")
485            try:
486                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
487                                       user="grue")
488                session.AddDBConnection(dbconn)
489                map = Map("Test Map")
490                session.AddMap(map)
491                store = NonConnectionStore(dbconn, "roads")
492                session.AddShapeStore(store)
493                layer = Layer("Roads to Nowhere", store)
494                map.AddLayer(layer)
495    
496                # Save the session
497                filename = self.temp_file_name(self.id() + ".thuban")
498                save_session(session, filename)
499    
500                # Read it back and compare
501                file = open(filename)
502                written = file.read()
503                file.close()
504                expected = '''<?xml version="1.0" encoding="UTF-8"?>
505                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
506                <session title="A PostGIS Session"
507                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
508                    <dbconnection id="DB"
509                                  dbtype="postgis" dbname="plugh"
510                                  host="xyzzy" port="42"
511                                  user="grue"/>
512                    <dbshapesource id="roads" dbconn="DB" tablename="roads"/>
513                    <map title="Test Map">
514                        <layer title="Roads to Nowhere"
515                               shapestore="roads" visible="true"
516                               stroke="#000000" stroke_width="1" fill="None"/>
517                    </map>
518                </session>'''
519                self.compare_xml(written, expected)
520                self.validate_data(written)
521            finally:
522                session.Destroy()
523    
524    
525    class MockDataStore:
526    
527        """A very simple data store that only has dependencies"""
528    
529        def __init__(self, name, *dependencies):
530            self.name = name
531            self.dependencies = dependencies
532    
533        def __repr__(self):
534            return self.name
535    
536        def Dependencies(self):
537            return self.dependencies
538    
539    
540    class TestStoreSort(unittest.TestCase):
541    
542        def check_sort(self, containers, sorted):
543            """Check whether the list of data containers is sorted"""
544            # check whether sorted is in the right order
545            seen = {}
546            for container in sorted:
547                self.failIf(id(container) in seen,
548                            "Container %r at least twice in %r" % (container,
549                                                                   sorted))
550                for dep in container.Dependencies():
551                    self.assert_(id(dep) in seen,
552                                 "Dependency %r of %r not yet seen" % (dep,
553                                                                       container))
554                seen[id(container)] = 1
555            # check whether all of containers is in sorted
556            for container in containers:
557                self.assert_(id(container) in seen,
558                             "Container %r in containers but not in sorted")
559            self.assertEquals(len(containers), len(sorted))
560    
561        def test_sort_data_stores(self):
562            """Test Thuban.Model.save.sort_data_stores"""
563            d1 = MockDataStore("d1")
564            d2 = MockDataStore("d2")
565            d3 = MockDataStore("d3", d1)
566            d4 = MockDataStore("d4", d1, d3)
567    
568            containers = [d4, d1, d2, d3]
569            self.check_sort(containers, sort_data_stores(containers))
570            containers = [d1, d3, d2, d4]
571            self.check_sort(containers, sort_data_stores(containers))
572    
573    
574    
575  if __name__ == "__main__":  if __name__ == "__main__":
576      # 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.1173  
changed lines
  Added in v.1664

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26