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

Legend:
Removed from v.530  
changed lines
  Added in v.2642

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26