/[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 1168 by jonathan, Thu Jun 12 12:42:50 2003 UTC revision 1677 by bh, Thu Aug 28 13:34:28 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"))
         self.assertEquals(writer.encode('&"\'<>'),  
                           "&amp;&quot;&apos;&lt;&gt;")  
         self.assertEquals(writer.encode(unicode('&"\'<>')),  
                           "&amp;&quot;&apos;&lt;&gt;")  
55    
56  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):          eq(writer.encode("\x80\x90\xc2\x100"),
57                             "\xc2\x80\xc2\x90\xc3\x82\x100")
58            eq(writer.encode(u"\x80\x90\xc2\x100"),
59                             "\xc2\x80\xc2\x90\xc3\x82\x100")
60            eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
61    
62            eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
63            eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
64    
65    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 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 105  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-0.9.dtd">\n'
115                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
116             'xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">'
117                             '\n</session>\n')
118    
119            self.validate_data(written_contents)
120    
121      def testSingleLayer(self):      def testSingleLayer(self):
122          """Save a session with a single map with a single layer"""          """Save a session with a single map with a single layer"""
# Line 128  class SaveSessionTest(unittest.TestCase, Line 138  class SaveSessionTest(unittest.TestCase,
138          written_contents = file.read()          written_contents = file.read()
139          file.close()          file.close()
140          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
141          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
142          <session title="single map&amp;layer">          <session title="single map&amp;layer"
143               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
144                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
145              <map title="Test Map">              <map title="Test Map">
146                  <projection name="Unknown">                  <projection name="Unknown">
147                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
148                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
149                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
150                  </projection>                  </projection>
151                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
152                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
153              </map>              </map>
154          </session>'''          </session>'''
155            
156          expected_contents = expected_template % \          expected_contents = expected_template % \
157              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
158               "true")               "true")
159    
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
160          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
161    
162            self.validate_data(written_contents)
163    
164          layer.SetVisible(False)          layer.SetVisible(False)
165          save_session(session, filename)          save_session(session, filename)
166    
# Line 159  class SaveSessionTest(unittest.TestCase, Line 170  class SaveSessionTest(unittest.TestCase,
170          expected_contents = expected_template % \          expected_contents = expected_template % \
171              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
172               "false")               "false")
   
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
173          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
174            self.validate_data(written_contents)
175    
176          session.Destroy()          session.Destroy()
177    
178      def testLayerProjection(self):      def testLayerProjection(self):
179            """Test saving layers with projections"""
180          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
181          session = Session("single map&layer")          session = Session("single map&layer")
182          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
# Line 181  class SaveSessionTest(unittest.TestCase, Line 190  class SaveSessionTest(unittest.TestCase,
190          layer.SetProjection(proj)          layer.SetProjection(proj)
191          map.AddLayer(layer)          map.AddLayer(layer)
192    
193          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
194          save_session(session, filename)          save_session(session, filename)
195          session.Destroy()          session.Destroy()
196    
# Line 189  class SaveSessionTest(unittest.TestCase, Line 198  class SaveSessionTest(unittest.TestCase,
198          written_contents = file.read()          written_contents = file.read()
199          file.close()          file.close()
200          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
201          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
202          <session title="single map&amp;layer">          <session title="single map&amp;layer"
203               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
204                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
205              <map title="Test Map">              <map title="Test Map">
206                  <projection name="Unknown">                  <projection name="Unknown">
207                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
208                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
209                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
210                  </projection>                  </projection>
211                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
212                  fill="None" stroke="#000000" stroke_width="1" visible="true">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
213                      <projection name="Layer Projection">                      <projection name="Layer Projection">
214                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
# Line 212  class SaveSessionTest(unittest.TestCase, Line 223  class SaveSessionTest(unittest.TestCase,
223          #print expected_contents          #print expected_contents
224          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
225    
226                    self.validate_data(written_contents)
227    
228      def testRasterLayer(self):      def testRasterLayer(self):
229          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
230          session = Session("single map&layer")          session = Session("single map&layer")
# Line 223  class SaveSessionTest(unittest.TestCase, Line 235  class SaveSessionTest(unittest.TestCase,
235                                 os.pardir, "Data", "iceland", "island.tif")                                 os.pardir, "Data", "iceland", "island.tif")
236          layer = RasterLayer("My RasterLayer", imgfile)          layer = RasterLayer("My RasterLayer", imgfile)
237          map.AddLayer(layer)          map.AddLayer(layer)
238                                                                                    
239          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("%s.thuban" % self.id())
240          save_session(session, filename)          save_session(session, filename)
241          session.Destroy()          session.Destroy()
242                                                                                    
243          file = open(filename)          file = open(filename)
244          written_contents = file.read()          written_contents = file.read()
245          file.close()          file.close()
246          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
247          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
248          <session title="single map&amp;layer">          <session title="single map&amp;layer"
249               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
250              <map title="Test Map">              <map title="Test Map">
251                  <rasterlayer title="My RasterLayer" filename="%s"                  <rasterlayer title="My RasterLayer" filename="%s"
252                               visible="true">                               visible="true">
253                  </rasterlayer>                  </rasterlayer>
254              </map>              </map>
255          </session>''' % os.path.join(os.path.dirname(__file__),          </session>''' % os.path.join(os.pardir, os.pardir, "Data", "iceland",
                                      os.pardir, "Data", "iceland",  
256                                       "island.tif")                                       "island.tif")
257          #print written_contents          #print written_contents
258          #print "********************************************"          #print "********************************************"
259          #print expected_contents          #print expected_contents
260          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
261    
262            self.validate_data(written_contents)
263    
264      def testClassifiedLayer(self):      def testClassifiedLayer(self):
265          """Save a session with a single map with a single layer          """Save a session with a single map with classifications"""
            with a classificaton.  
         """  
266          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
267          session = Session("single map&layer")          session = Session("Map with Classifications")
268          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
269          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
270          session.AddMap(map)          session.AddMap(map)
# Line 261  class SaveSessionTest(unittest.TestCase, Line 273  class SaveSessionTest(unittest.TestCase,
273                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
274          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
275          map.AddLayer(layer)          map.AddLayer(layer)
276            layer2 = Layer("My Layer", layer.ShapeStore())
277            map.AddLayer(layer2)
278    
279          clazz = layer.GetClassification()          clazz = layer.GetClassification()
280    
281          clazz.SetField("AREA")          layer.SetClassificationColumn("AREA")
282    
283          clazz.AppendGroup(ClassGroupSingleton(42,          clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
284                                             ClassGroupProperties(),                                                "single"))
285                                             "single"))          clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
286          clazz.AppendGroup(ClassGroupSingleton("text",                                                "single-text"))
                                            ClassGroupProperties(),  
                                            "single-text"))  
287    
288          clazz.AppendGroup(ClassGroupRange(0, 42,          clazz.AppendGroup(ClassGroupRange((0, 42),
289                                             ClassGroupProperties(),                                             ClassGroupProperties(),
290                                             "range"))                                             "range"))
291    
# Line 282  class SaveSessionTest(unittest.TestCase, Line 294  class SaveSessionTest(unittest.TestCase,
294          range.SetLabel("new-range")          range.SetLabel("new-range")
295          clazz.AppendGroup(range)          clazz.AppendGroup(range)
296    
297          filename = self.temp_file_name("save_singlemap.thuban")  
298            clazz = layer2.GetClassification()
299            layer2.SetClassificationColumn("POPYCOUN")
300    
301            # Classification with Latin 1 text
302            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
303                                                  ClassGroupProperties(),
304                                                  '\xdcml\xe4uts')) # Uemlaeuts
305    
306    
307            filename = self.temp_file_name("%s.thuban" % self.id())
308          save_session(session, filename)          save_session(session, filename)
309    
310          file = open(filename)          file = open(filename)
311          written_contents = file.read()          written_contents = file.read()
312          file.close()          file.close()
313          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
314          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
315          <session title="single map&amp;layer">          <session title="Map with Classifications"
316               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
317                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
318              <map title="Test Map">              <map title="Test Map">
319                  <projection name="Unknown">                  <projection name="Unknown">
320                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
321                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
322                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
323                  </projection>                  </projection>
324                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
325                  fill="None" stroke="#000000" stroke_width="1" visible="%s">                  fill="None" stroke="#000000" stroke_width="1" visible="%s">
326                      <classification field="AREA" field_type="double">                      <classification field="AREA" field_type="double">
327                          <clnull label="">                          <clnull label="">
# Line 317  class SaveSessionTest(unittest.TestCase, Line 341  class SaveSessionTest(unittest.TestCase,
341                          </clrange>                          </clrange>
342                      </classification>                      </classification>
343                  </layer>                  </layer>
344                    <layer title="My Layer" shapestore="D1"
345                    fill="None" stroke="#000000" stroke_width="1" visible="true">
346                        <classification field="POPYCOUN" field_type="string">
347                            <clnull label="">
348                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
349                            </clnull>
350                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
351                                 label="\xc3\x9cml\xc3\xa4uts">
352                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
353                            </clpoint>
354                        </classification>
355                    </layer>
356              </map>              </map>
357          </session>'''          </session>'''
358            
359          expected_contents = expected_template % \          expected_contents = expected_template % \
360              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
361               "true")               "true")
# Line 329  class SaveSessionTest(unittest.TestCase, Line 365  class SaveSessionTest(unittest.TestCase,
365          #print expected_contents          #print expected_contents
366          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
367    
368            self.validate_data(written_contents)
369    
370          session.Destroy()          session.Destroy()
371    
372        def test_dbf_table(self):
373            """Test saving a session with a dbf table link"""
374            session = self.session = Session("a DBF Table session")
375            # use shapefile from the example data
376            dbffile = os.path.join(os.path.dirname(__file__),
377                                   os.pardir, "Data", "iceland", "political.dbf")
378            table = session.AddTable(DBFTable(dbffile))
379    
380            filename = self.temp_file_name("save_singletable.thuban")
381            save_session(session, filename)
382    
383            file = open(filename)
384            written_contents = file.read()
385            file.close()
386            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
387            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
388            <session title="a DBF Table session"
389               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
390                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
391            </session>'''
392    
393            expected_contents = (expected_template
394                                 % os.path.join(os.pardir, os.pardir, "Data",
395                                                "iceland", "political.dbf"))
396            self.compare_xml(written_contents, expected_contents)
397            self.validate_data(written_contents)
398    
399        def test_joined_table(self):
400            """Test saving a session with joined table"""
401            # Create a simple table to use in the join
402            dbffile = self.temp_file_name("save_joinedtable.dbf")
403            dbf = dbflib.create(dbffile)
404            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
405            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
406            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
407            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
408            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
409            dbf.close()
410    
411            # Create the session and a map
412            session = Session("A Joined Table session")
413            try:
414                map = Map("Test Map")
415                session.AddMap(map)
416    
417                # Add the dbf file to the session
418                dbftable = session.AddTable(DBFTable(dbffile))
419    
420                # Create a layer with the shapefile to use in the join
421                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
422                                       os.pardir, "Data", "iceland",
423                                       "roads-line.shp")
424                layer = Layer("My Layer", session.OpenShapefile(shpfile))
425                map.AddLayer(layer)
426    
427                # Do the join
428                store = layer.ShapeStore()
429                #for col in store.Table().Columns():
430                #    print col.name
431                joined = TransientJoinedTable(session.TransientDB(),
432                                              store.Table(), "RDLNTYPE",
433                                              dbftable, "RDTYPE",
434                                              outer_join = True)
435                store = session.AddShapeStore(DerivedShapeStore(store, joined))
436                layer.SetShapeStore(store)
437    
438                # Save the session
439                filename = self.temp_file_name("save_joinedtable.thuban")
440                save_session(session, filename)
441    
442                # Read it back and compare
443                file = open(filename)
444                written_contents = file.read()
445                file.close()
446                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
447                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
448                <session title="A Joined Table session"
449                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
450                    <fileshapesource filename="%(shpfile)s"
451                                     filetype="shapefile" id="D142197204"/>
452                    <filetable filename="%(dbffile)s"
453                               title="save_joinedtable"
454                               filetype="DBF" id="D141881756"/>
455                    <jointable id="D142180284"
456                               title="Join of roads-line and save_joinedtable"
457                               leftcolumn="RDLNTYPE" left="D142197204"
458                               rightcolumn="RDTYPE" right="D141881756"
459                               jointype="LEFT OUTER" />
460                    <derivedshapesource id="D141915644"
461                                        table="D142180284"
462                                        shapesource="D142197204"/>
463                    <map title="Test Map">
464                        <layer title="My Layer"
465                               shapestore="D141915644" visible="true"
466                               stroke="#000000" stroke_width="1" fill="None"/>
467                    </map>
468                </session>'''
469    
470                expected_contents = expected_template % {
471                    "dbffile": relative_filename(self.temp_dir(), dbffile),
472                    "shpfile": relative_filename(self.temp_dir(), shpfile)
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                    pass
493    
494            session = Session("A PostGIS Session")
495            try:
496                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
497                                       user="grue")
498                session.AddDBConnection(dbconn)
499                map = Map("Test Map")
500                session.AddMap(map)
501                store = NonConnectionStore(dbconn, "roads")
502                session.AddShapeStore(store)
503                layer = Layer("Roads to Nowhere", store)
504                map.AddLayer(layer)
505    
506                # Save the session
507                filename = self.temp_file_name(self.id() + ".thuban")
508                save_session(session, filename)
509    
510                # Read it back and compare
511                file = open(filename)
512                written = file.read()
513                file.close()
514                expected = '''<?xml version="1.0" encoding="UTF-8"?>
515                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
516                <session title="A PostGIS Session"
517                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
518                    <dbconnection id="DB"
519                                  dbtype="postgis" dbname="plugh"
520                                  host="xyzzy" port="42"
521                                  user="grue"/>
522                    <dbshapesource id="roads" dbconn="DB" tablename="roads"/>
523                    <map title="Test Map">
524                        <layer title="Roads to Nowhere"
525                               shapestore="roads" visible="true"
526                               stroke="#000000" stroke_width="1" fill="None"/>
527                    </map>
528                </session>'''
529                self.compare_xml(written, expected)
530                self.validate_data(written)
531            finally:
532                session.Destroy()
533    
534    
535    class MockDataStore:
536    
537        """A very simple data store that only has dependencies"""
538    
539        def __init__(self, name, *dependencies):
540            self.name = name
541            self.dependencies = dependencies
542    
543        def __repr__(self):
544            return self.name
545    
546        def Dependencies(self):
547            return self.dependencies
548    
549    
550    class TestStoreSort(unittest.TestCase):
551    
552        def check_sort(self, containers, sorted):
553            """Check whether the list of data containers is sorted"""
554            # check whether sorted is in the right order
555            seen = {}
556            for container in sorted:
557                self.failIf(id(container) in seen,
558                            "Container %r at least twice in %r" % (container,
559                                                                   sorted))
560                for dep in container.Dependencies():
561                    self.assert_(id(dep) in seen,
562                                 "Dependency %r of %r not yet seen" % (dep,
563                                                                       container))
564                seen[id(container)] = 1
565            # check whether all of containers is in sorted
566            for container in containers:
567                self.assert_(id(container) in seen,
568                             "Container %r in containers but not in sorted")
569            self.assertEquals(len(containers), len(sorted))
570    
571        def test_sort_data_stores(self):
572            """Test Thuban.Model.save.sort_data_stores"""
573            d1 = MockDataStore("d1")
574            d2 = MockDataStore("d2")
575            d3 = MockDataStore("d3", d1)
576            d4 = MockDataStore("d4", d1, d3)
577    
578            containers = [d4, d1, d2, d3]
579            self.check_sort(containers, sort_data_stores(containers))
580            containers = [d1, d3, d2, d4]
581            self.check_sort(containers, sort_data_stores(containers))
582    
583    
584    
585  if __name__ == "__main__":  if __name__ == "__main__":
586      # 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.1168  
changed lines
  Added in v.1677

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26