/[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 1687 by bh, Fri Aug 29 10:02:16 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,
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  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):      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 110  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 133  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 164  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 = self.session = Session("single map&layer")
182          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
183          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
184          session.AddMap(map)          session.AddMap(map)
# Line 182  class SaveSessionTest(unittest.TestCase, Line 186  class SaveSessionTest(unittest.TestCase,
186          shpfile = os.path.join(os.path.dirname(__file__),          shpfile = os.path.join(os.path.dirname(__file__),
187                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
188          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
189          proj = Projection(["proj=lcc", "ellps=clrk66"], "Layer Projection")          proj = Projection(["proj=lcc", "ellps=clrk66",
190                               "lat_1=0", "lat_2=20"],
191                              "Layer Projection")
192          layer.SetProjection(proj)          layer.SetProjection(proj)
193          map.AddLayer(layer)          map.AddLayer(layer)
194    
195          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
196          save_session(session, filename)          save_session(session, filename)
         session.Destroy()  
197    
198          file = open(filename)          file = open(filename)
199          written_contents = file.read()          written_contents = file.read()
200          file.close()          file.close()
201          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
202          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
203          <session title="single map&amp;layer">          <session title="single map&amp;layer"
204               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
205                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
206              <map title="Test Map">              <map title="Test Map">
207                  <projection name="Unknown">                  <projection name="Unknown">
208                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
209                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
210                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
211                  </projection>                  </projection>
212                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
213                  fill="None" stroke="#000000" stroke_width="1" visible="true">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
214                      <projection name="Layer Projection">                      <projection name="Layer Projection">
215                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
216                          <parameter value="ellps=clrk66"/>                          <parameter value="ellps=clrk66"/>
217                            <parameter value="lat_1=0"/>
218                            <parameter value="lat_2=20"/>
219                      </projection>                      </projection>
220                  </layer>                  </layer>
221              </map>              </map>
# Line 217  class SaveSessionTest(unittest.TestCase, Line 226  class SaveSessionTest(unittest.TestCase,
226          #print expected_contents          #print expected_contents
227          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
228    
229                    self.validate_data(written_contents)
230    
231      def testRasterLayer(self):      def testRasterLayer(self):
232          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
233          session = Session("single map&layer")          session = Session("single map&layer")
# Line 228  class SaveSessionTest(unittest.TestCase, Line 238  class SaveSessionTest(unittest.TestCase,
238                                 os.pardir, "Data", "iceland", "island.tif")                                 os.pardir, "Data", "iceland", "island.tif")
239          layer = RasterLayer("My RasterLayer", imgfile)          layer = RasterLayer("My RasterLayer", imgfile)
240          map.AddLayer(layer)          map.AddLayer(layer)
241                                                                                    
242          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("%s.thuban" % self.id())
243          save_session(session, filename)          save_session(session, filename)
244          session.Destroy()          session.Destroy()
245                                                                                    
246          file = open(filename)          file = open(filename)
247          written_contents = file.read()          written_contents = file.read()
248          file.close()          file.close()
249          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
250          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
251          <session title="single map&amp;layer">          <session title="single map&amp;layer"
252               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
253              <map title="Test Map">              <map title="Test Map">
254                  <rasterlayer title="My RasterLayer" filename="%s"                  <rasterlayer title="My RasterLayer" filename="%s"
255                               visible="true">                               visible="true">
256                  </rasterlayer>                  </rasterlayer>
257              </map>              </map>
258          </session>''' % os.path.join(os.path.dirname(__file__),          </session>''' % os.path.join(os.pardir, os.pardir, "Data", "iceland",
                                      os.pardir, "Data", "iceland",  
259                                       "island.tif")                                       "island.tif")
260          #print written_contents          #print written_contents
261          #print "********************************************"          #print "********************************************"
262          #print expected_contents          #print expected_contents
263          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
264    
265            self.validate_data(written_contents)
266    
267      def testClassifiedLayer(self):      def testClassifiedLayer(self):
268          """Save a session with a single map with a single layer          """Save a session with a single map with classifications"""
            with a classificaton.  
         """  
269          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
270          session = Session("single map&layer")          session = Session("Map with Classifications")
271          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
272          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
273          session.AddMap(map)          session.AddMap(map)
# Line 266  class SaveSessionTest(unittest.TestCase, Line 276  class SaveSessionTest(unittest.TestCase,
276                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
277          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
278          map.AddLayer(layer)          map.AddLayer(layer)
279            layer2 = Layer("My Layer", layer.ShapeStore())
280            map.AddLayer(layer2)
281    
282          clazz = layer.GetClassification()          clazz = layer.GetClassification()
283    
284          clazz.SetField("AREA")          layer.SetClassificationColumn("AREA")
285    
286          clazz.AppendGroup(ClassGroupSingleton(42,          clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
287                                             ClassGroupProperties(),                                                "single"))
288                                             "single"))          clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
289          clazz.AppendGroup(ClassGroupSingleton("text",                                                "single-text"))
                                            ClassGroupProperties(),  
                                            "single-text"))  
290    
291          clazz.AppendGroup(ClassGroupRange(0, 42,          clazz.AppendGroup(ClassGroupRange((0, 42),
292                                             ClassGroupProperties(),                                             ClassGroupProperties(),
293                                             "range"))                                             "range"))
294    
# Line 287  class SaveSessionTest(unittest.TestCase, Line 297  class SaveSessionTest(unittest.TestCase,
297          range.SetLabel("new-range")          range.SetLabel("new-range")
298          clazz.AppendGroup(range)          clazz.AppendGroup(range)
299    
300          filename = self.temp_file_name("save_singlemap.thuban")  
301            clazz = layer2.GetClassification()
302            layer2.SetClassificationColumn("POPYCOUN")
303    
304            # Classification with Latin 1 text
305            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
306                                                  ClassGroupProperties(),
307                                                  '\xdcml\xe4uts')) # Uemlaeuts
308    
309    
310            filename = self.temp_file_name("%s.thuban" % self.id())
311          save_session(session, filename)          save_session(session, filename)
312    
313          file = open(filename)          file = open(filename)
314          written_contents = file.read()          written_contents = file.read()
315          file.close()          file.close()
316          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
317          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
318          <session title="single map&amp;layer">          <session title="Map with Classifications"
319               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
320                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
321              <map title="Test Map">              <map title="Test Map">
322                  <projection name="Unknown">                  <projection name="Unknown">
323                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
324                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
325                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
326                  </projection>                  </projection>
327                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
328                  fill="None" stroke="#000000" stroke_width="1" visible="%s">                  fill="None" stroke="#000000" stroke_width="1" visible="%s">
329                      <classification field="AREA" field_type="double">                      <classification field="AREA" field_type="double">
330                          <clnull label="">                          <clnull label="">
# Line 322  class SaveSessionTest(unittest.TestCase, Line 344  class SaveSessionTest(unittest.TestCase,
344                          </clrange>                          </clrange>
345                      </classification>                      </classification>
346                  </layer>                  </layer>
347                    <layer title="My Layer" shapestore="D1"
348                    fill="None" stroke="#000000" stroke_width="1" visible="true">
349                        <classification field="POPYCOUN" field_type="string">
350                            <clnull label="">
351                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
352                            </clnull>
353                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
354                                 label="\xc3\x9cml\xc3\xa4uts">
355                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
356                            </clpoint>
357                        </classification>
358                    </layer>
359              </map>              </map>
360          </session>'''          </session>'''
361            
362          expected_contents = expected_template % \          expected_contents = expected_template % \
363              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
364               "true")               "true")
# Line 334  class SaveSessionTest(unittest.TestCase, Line 368  class SaveSessionTest(unittest.TestCase,
368          #print expected_contents          #print expected_contents
369          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
370    
371            self.validate_data(written_contents)
372    
373          session.Destroy()          session.Destroy()
374    
375        def test_dbf_table(self):
376            """Test saving a session with a dbf table link"""
377            session = self.session = Session("a DBF Table session")
378            # use shapefile from the example data
379            dbffile = os.path.join(os.path.dirname(__file__),
380                                   os.pardir, "Data", "iceland", "political.dbf")
381            table = session.AddTable(DBFTable(dbffile))
382    
383            filename = self.temp_file_name("save_singletable.thuban")
384            save_session(session, filename)
385    
386            file = open(filename)
387            written_contents = file.read()
388            file.close()
389            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
390            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
391            <session title="a DBF Table session"
392               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
393                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
394            </session>'''
395    
396            expected_contents = (expected_template
397                                 % os.path.join(os.pardir, os.pardir, "Data",
398                                                "iceland", "political.dbf"))
399            self.compare_xml(written_contents, expected_contents)
400            self.validate_data(written_contents)
401    
402        def test_joined_table(self):
403            """Test saving a session with joined table"""
404            # Create a simple table to use in the join
405            dbffile = self.temp_file_name("save_joinedtable.dbf")
406            dbf = dbflib.create(dbffile)
407            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
408            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
409            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
410            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
411            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
412            dbf.close()
413    
414            # Create the session and a map
415            session = Session("A Joined Table session")
416            try:
417                map = Map("Test Map")
418                session.AddMap(map)
419    
420                # Add the dbf file to the session
421                dbftable = session.AddTable(DBFTable(dbffile))
422    
423                # Create a layer with the shapefile to use in the join
424                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
425                                       os.pardir, "Data", "iceland",
426                                       "roads-line.shp")
427                layer = Layer("My Layer", session.OpenShapefile(shpfile))
428                map.AddLayer(layer)
429    
430                # Do the join
431                store = layer.ShapeStore()
432                #for col in store.Table().Columns():
433                #    print col.name
434                joined = TransientJoinedTable(session.TransientDB(),
435                                              store.Table(), "RDLNTYPE",
436                                              dbftable, "RDTYPE",
437                                              outer_join = True)
438                store = session.AddShapeStore(DerivedShapeStore(store, joined))
439                layer.SetShapeStore(store)
440    
441                # Save the session
442                filename = self.temp_file_name("save_joinedtable.thuban")
443                save_session(session, filename)
444    
445                # Read it back and compare
446                file = open(filename)
447                written_contents = file.read()
448                file.close()
449                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
450                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
451                <session title="A Joined Table session"
452                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
453                    <fileshapesource filename="%(shpfile)s"
454                                     filetype="shapefile" id="D142197204"/>
455                    <filetable filename="%(dbffile)s"
456                               title="save_joinedtable"
457                               filetype="DBF" id="D141881756"/>
458                    <jointable id="D142180284"
459                               title="Join of roads-line and save_joinedtable"
460                               leftcolumn="RDLNTYPE" left="D142197204"
461                               rightcolumn="RDTYPE" right="D141881756"
462                               jointype="LEFT OUTER" />
463                    <derivedshapesource id="D141915644"
464                                        table="D142180284"
465                                        shapesource="D142197204"/>
466                    <map title="Test Map">
467                        <layer title="My Layer"
468                               shapestore="D141915644" visible="true"
469                               stroke="#000000" stroke_width="1" fill="None"/>
470                    </map>
471                </session>'''
472    
473                expected_contents = expected_template % {
474                    "dbffile": relative_filename(self.temp_dir(), dbffile),
475                    "shpfile": relative_filename(self.temp_dir(), shpfile)
476                    }
477                self.compare_xml(written_contents, expected_contents)
478                self.validate_data(written_contents)
479            finally:
480                session.Destroy()
481                session = None
482    
483    
484        def test_save_postgis(self):
485            """Test saving a session with a postgis connection"""
486    
487            class NonConnection(PostGISConnection):
488                """connection class that doesn't actually connect """
489                def connect(self):
490                    pass
491    
492            class NonConnectionStore(PostGISShapeStore):
493                """Shapestore that doesn't try to access the server"""
494                def _fetch_table_information(self):
495                    pass
496    
497            session = Session("A PostGIS Session")
498            try:
499                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
500                                       user="grue")
501                session.AddDBConnection(dbconn)
502                map = Map("Test Map")
503                session.AddMap(map)
504                store = NonConnectionStore(dbconn, "roads")
505                session.AddShapeStore(store)
506                layer = Layer("Roads to Nowhere", store)
507                map.AddLayer(layer)
508    
509                # Save the session
510                filename = self.temp_file_name(self.id() + ".thuban")
511                save_session(session, filename)
512    
513                # Read it back and compare
514                file = open(filename)
515                written = file.read()
516                file.close()
517                expected = '''<?xml version="1.0" encoding="UTF-8"?>
518                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
519                <session title="A PostGIS Session"
520                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
521                    <dbconnection id="DB"
522                                  dbtype="postgis" dbname="plugh"
523                                  host="xyzzy" port="42"
524                                  user="grue"/>
525                    <dbshapesource id="roads" dbconn="DB" tablename="roads"/>
526                    <map title="Test Map">
527                        <layer title="Roads to Nowhere"
528                               shapestore="roads" visible="true"
529                               stroke="#000000" stroke_width="1" fill="None"/>
530                    </map>
531                </session>'''
532                self.compare_xml(written, expected)
533                self.validate_data(written)
534            finally:
535                session.Destroy()
536    
537    
538    class MockDataStore:
539    
540        """A very simple data store that only has dependencies"""
541    
542        def __init__(self, name, *dependencies):
543            self.name = name
544            self.dependencies = dependencies
545    
546        def __repr__(self):
547            return self.name
548    
549        def Dependencies(self):
550            return self.dependencies
551    
552    
553    class TestStoreSort(unittest.TestCase):
554    
555        def check_sort(self, containers, sorted):
556            """Check whether the list of data containers is sorted"""
557            # check whether sorted is in the right order
558            seen = {}
559            for container in sorted:
560                self.failIf(id(container) in seen,
561                            "Container %r at least twice in %r" % (container,
562                                                                   sorted))
563                for dep in container.Dependencies():
564                    self.assert_(id(dep) in seen,
565                                 "Dependency %r of %r not yet seen" % (dep,
566                                                                       container))
567                seen[id(container)] = 1
568            # check whether all of containers is in sorted
569            for container in containers:
570                self.assert_(id(container) in seen,
571                             "Container %r in containers but not in sorted")
572            self.assertEquals(len(containers), len(sorted))
573    
574        def test_sort_data_stores(self):
575            """Test Thuban.Model.save.sort_data_stores"""
576            d1 = MockDataStore("d1")
577            d2 = MockDataStore("d2")
578            d3 = MockDataStore("d3", d1)
579            d4 = MockDataStore("d4", d1, d3)
580    
581            containers = [d4, d1, d2, d3]
582            self.check_sort(containers, sort_data_stores(containers))
583            containers = [d1, d3, d2, d4]
584            self.check_sort(containers, sort_data_stores(containers))
585    
586    
587    
588  if __name__ == "__main__":  if __name__ == "__main__":
589      # 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.1687

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26