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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26