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

Legend:
Removed from v.775  
changed lines
  Added in v.2621

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26