/[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 1245 by bh, Thu Jun 19 19:29:23 2003 UTC revision 1452 by bh, Fri Jul 18 12:57:59 2003 UTC
# Line 26  import xmlsupport Line 26  import xmlsupport
26  import support  import support
27  support.initthuban()  support.initthuban()
28    
29  from Thuban.Model.save import XMLWriter, save_session  import dbflib
30    
31    from Thuban.Lib.fileutil import relative_filename
32    from Thuban.Model.save import XMLWriter, save_session, sort_data_stores
33  from Thuban.Model.session import Session  from Thuban.Model.session import Session
34  from Thuban.Model.map import Map  from Thuban.Model.map import Map
35  from Thuban.Model.layer import Layer, RasterLayer  from Thuban.Model.layer import Layer, RasterLayer
36  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
37    from Thuban.Model.table import DBFTable
38    from Thuban.Model.transientdb import TransientJoinedTable
39    from Thuban.Model.data import DerivedShapeStore
40    
41  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
42      ClassGroupProperties      ClassGroupProperties
# Line 38  from Thuban.Model.classification import Line 44  from Thuban.Model.classification import
44  from Thuban.Model.range import Range  from Thuban.Model.range import Range
45    
46    
 class SaxEventLister(xml.sax.handler.ContentHandler):  
   
     def __init__(self):  
         self.eventlist = []  
   
     def startElementNS(self, name, qname, attrs):  
         items = attrs.items()  
         items.sort()  
         self.eventlist.append(("start", name, qname, items))  
   
     def endElementNS(self, name, qname):  
         self.eventlist.append(("end", name, qname))  
   
   
 def sax_eventlist(data):  
     """Return a list of SAX event generated for the XML data.  
     """  
     handler = SaxEventLister()  
     parser = make_parser()  
     parser.setContentHandler(handler)  
     parser.setErrorHandler(ErrorHandler())  
     parser.setFeature(xml.sax.handler.feature_namespaces, 1)  
   
     #  
     # see comment at the end of Thuban/Model/load.py  
     #  
     try:  
         parser.setFeature(xml.sax.handler.feature_validation, 0)  
         parser.setFeature(xml.sax.handler.feature_external_ges, 0)  
         parser.setFeature(xml.sax.handler.feature_external_pes, 0)  
     except SAXNotRecognizedException:  
         pass  
   
     inpsrc = xml.sax.InputSource()  
     inpsrc.setByteStream(StringIO(data))  
     parser.parse(inpsrc)  
   
     return handler.eventlist  
   
47  class XMLWriterTest(unittest.TestCase):  class XMLWriterTest(unittest.TestCase):
48    
49      def testEncode(self):      def testEncode(self):
# Line 99  class XMLWriterTest(unittest.TestCase): Line 66  class XMLWriterTest(unittest.TestCase):
66  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
67                        xmlsupport.ValidationTest):                        xmlsupport.ValidationTest):
68    
69        dtd = "http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd"
70        thubanids = [((dtd, n), (None, "id")) for n in
71                     ["fileshapesource", "filetable", "jointable",
72                      "derivedshapesource"]]
73        thubanidrefs = [((dtd, n), (None, m)) for n, m in
74                        [("layer", "shapestore"),
75                         ("jointable", "left"),
76                         ("jointable", "right"),
77                         ("derivedshapesource", "table"),
78                         ("derivedshapesource", "shapesource")]]
79        del n, m, dtd
80    
81      def compare_xml(self, xml1, xml2):      def compare_xml(self, xml1, xml2):
82          self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))          list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
83                                             idrefs = self.thubanidrefs)
84            list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
85                                             idrefs = self.thubanidrefs)
86            if list1 != list2:
87                for a, b in zip(list1, list2):
88                    if a != b:
89                        self.fail("%r != %r" % (a, b))
90    
91    
92      def testEmptySession(self):      def testEmptySession(self):
93          """Save an empty session"""          """Save an empty session"""
# Line 114  class SaveSessionTest(unittest.TestCase, Line 101  class SaveSessionTest(unittest.TestCase,
101          file.close()          file.close()
102          self.compare_xml(written_contents,          self.compare_xml(written_contents,
103                           '<?xml version="1.0" encoding="UTF-8"?>\n'                           '<?xml version="1.0" encoding="UTF-8"?>\n'
104                           '<!DOCTYPE session SYSTEM "thuban.dtd">\n'                           '<!DOCTYPE session SYSTEM "thuban-0.9.dtd">\n'
105                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
106             'xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">'
107                             '\n</session>\n')
108    
109          self.validate_data(written_contents)          self.validate_data(written_contents)
110    
# Line 139  class SaveSessionTest(unittest.TestCase, Line 128  class SaveSessionTest(unittest.TestCase,
128          written_contents = file.read()          written_contents = file.read()
129          file.close()          file.close()
130          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
131          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
132          <session title="single map&amp;layer">          <session title="single map&amp;layer"
133               xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
134                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
135              <map title="Test Map">              <map title="Test Map">
136                  <projection name="Unknown">                  <projection name="Unknown">
137                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
138                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
139                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
140                  </projection>                  </projection>
141                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
142                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
143              </map>              </map>
144          </session>'''          </session>'''
145            
146          expected_contents = expected_template % \          expected_contents = expected_template % \
147              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
148               "true")               "true")
149    
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
150          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
151    
152          self.validate_data(written_contents)          self.validate_data(written_contents)
# Line 172  class SaveSessionTest(unittest.TestCase, Line 160  class SaveSessionTest(unittest.TestCase,
160          expected_contents = expected_template % \          expected_contents = expected_template % \
161              (os.path.join("..", "..", "Data", "iceland", "political.shp"),              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
162               "false")               "false")
   
         #print written_contents  
         #print "********************************************"  
         #print expected_contents  
163          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
164          self.validate_data(written_contents)          self.validate_data(written_contents)
165    
166          session.Destroy()          session.Destroy()
167    
168      def testLayerProjection(self):      def testLayerProjection(self):
169            """Test saving layers with projections"""
170          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
171          session = Session("single map&layer")          session = Session("single map&layer")
172          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
# Line 195  class SaveSessionTest(unittest.TestCase, Line 180  class SaveSessionTest(unittest.TestCase,
180          layer.SetProjection(proj)          layer.SetProjection(proj)
181          map.AddLayer(layer)          map.AddLayer(layer)
182    
183          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
184          save_session(session, filename)          save_session(session, filename)
185          session.Destroy()          session.Destroy()
186    
# Line 203  class SaveSessionTest(unittest.TestCase, Line 188  class SaveSessionTest(unittest.TestCase,
188          written_contents = file.read()          written_contents = file.read()
189          file.close()          file.close()
190          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
191          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
192          <session title="single map&amp;layer">          <session title="single map&amp;layer"
193               xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
194                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
195              <map title="Test Map">              <map title="Test Map">
196                  <projection name="Unknown">                  <projection name="Unknown">
197                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
198                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
199                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
200                  </projection>                  </projection>
201                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
202                  fill="None" stroke="#000000" stroke_width="1" visible="true">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
203                      <projection name="Layer Projection">                      <projection name="Layer Projection">
204                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
# Line 247  class SaveSessionTest(unittest.TestCase, Line 234  class SaveSessionTest(unittest.TestCase,
234          written_contents = file.read()          written_contents = file.read()
235          file.close()          file.close()
236          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
237          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
238          <session title="single map&amp;layer">          <session title="single map&amp;layer"
239               xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
240              <map title="Test Map">              <map title="Test Map">
241                  <rasterlayer title="My RasterLayer" filename="%s"                  <rasterlayer title="My RasterLayer" filename="%s"
242                               visible="true">                               visible="true">
243                  </rasterlayer>                  </rasterlayer>
244              </map>              </map>
245          </session>''' % os.path.join(os.path.dirname(__file__),          </session>''' % os.path.join(os.path.dirname(__file__),
246                                       os.pardir, "Data", "iceland",                                       os.pardir, "Data", "iceland",
247                                       "island.tif")                                       "island.tif")
248          #print written_contents          #print written_contents
# Line 265  class SaveSessionTest(unittest.TestCase, Line 253  class SaveSessionTest(unittest.TestCase,
253          self.validate_data(written_contents)          self.validate_data(written_contents)
254    
255      def testClassifiedLayer(self):      def testClassifiedLayer(self):
256          """Save a session with a single map with a single layer          """Save a session with a single map with classifications"""
            with a classificaton.  
         """  
257          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
258          session = Session("single map&layer")          session = Session("Map with Classifications")
259          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
260          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
261          session.AddMap(map)          session.AddMap(map)
# Line 278  class SaveSessionTest(unittest.TestCase, Line 264  class SaveSessionTest(unittest.TestCase,
264                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
265          layer = Layer("My Layer", session.OpenShapefile(shpfile))          layer = Layer("My Layer", session.OpenShapefile(shpfile))
266          map.AddLayer(layer)          map.AddLayer(layer)
267            layer2 = Layer("My Layer", layer.ShapeStore())
268            map.AddLayer(layer2)
269    
270          clazz = layer.GetClassification()          clazz = layer.GetClassification()
271    
272          clazz.SetField("AREA")          layer.SetClassificationColumn("AREA")
273    
274          clazz.AppendGroup(ClassGroupSingleton(42,          clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
275                                             ClassGroupProperties(),                                                "single"))
276                                             "single"))          clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
277          clazz.AppendGroup(ClassGroupSingleton("text",                                                "single-text"))
                                            ClassGroupProperties(),  
                                            "single-text"))  
278    
279          clazz.AppendGroup(ClassGroupRange(0, 42,          clazz.AppendGroup(ClassGroupRange((0, 42),
280                                             ClassGroupProperties(),                                             ClassGroupProperties(),
281                                             "range"))                                             "range"))
282    
# Line 299  class SaveSessionTest(unittest.TestCase, Line 285  class SaveSessionTest(unittest.TestCase,
285          range.SetLabel("new-range")          range.SetLabel("new-range")
286          clazz.AppendGroup(range)          clazz.AppendGroup(range)
287    
288          filename = self.temp_file_name("save_singlemap.thuban")  
289            clazz = layer2.GetClassification()
290            layer2.SetClassificationColumn("POPYCOUN")
291    
292            # Classification with Latin 1 text
293            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
294                                                  ClassGroupProperties(),
295                                                  '\xdcml\xe4uts')) # Uemlaeuts
296    
297    
298            filename = self.temp_file_name("%s.thuban" % self.id())
299          save_session(session, filename)          save_session(session, filename)
300    
301          file = open(filename)          file = open(filename)
302          written_contents = file.read()          written_contents = file.read()
303          file.close()          file.close()
304          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
305          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
306          <session title="single map&amp;layer">          <session title="Map with Classifications"
307               xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
308                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
309              <map title="Test Map">              <map title="Test Map">
310                  <projection name="Unknown">                  <projection name="Unknown">
311                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
312                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
313                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
314                  </projection>                  </projection>
315                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
316                  fill="None" stroke="#000000" stroke_width="1" visible="%s">                  fill="None" stroke="#000000" stroke_width="1" visible="%s">
317                      <classification field="AREA" field_type="double">                      <classification field="AREA" field_type="double">
318                          <clnull label="">                          <clnull label="">
# Line 334  class SaveSessionTest(unittest.TestCase, Line 332  class SaveSessionTest(unittest.TestCase,
332                          </clrange>                          </clrange>
333                      </classification>                      </classification>
334                  </layer>                  </layer>
335                    <layer title="My Layer" shapestore="D1"
336                    fill="None" stroke="#000000" stroke_width="1" visible="true">
337                        <classification field="POPYCOUN" field_type="string">
338                            <clnull label="">
339                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
340                            </clnull>
341                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
342                                 label="\xc3\x9cml\xc3\xa4uts">
343                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
344                            </clpoint>
345                        </classification>
346                    </layer>
347              </map>              </map>
348          </session>'''          </session>'''
349    
# Line 350  class SaveSessionTest(unittest.TestCase, Line 360  class SaveSessionTest(unittest.TestCase,
360    
361          session.Destroy()          session.Destroy()
362    
363        def test_dbf_table(self):
364            """Test saving a session with a dbf table link"""
365            session = Session("a DBF Table session")
366            # use shapefile from the example data
367            dbffile = os.path.join(os.path.dirname(__file__),
368                                   os.pardir, "Data", "iceland", "political.dbf")
369            table = session.AddTable(DBFTable(dbffile))
370    
371            filename = self.temp_file_name("save_singletable.thuban")
372            save_session(session, filename)
373    
374            file = open(filename)
375            written_contents = file.read()
376            file.close()
377            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
378            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
379            <session title="a DBF Table session"
380               xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
381                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
382            </session>'''
383    
384            expected_contents = expected_template % dbffile
385            self.compare_xml(written_contents, expected_contents)
386    
387        def test_joined_table(self):
388            """Test saving a session with joined table"""
389            # Create a simple table to use in the join
390            dbffile = self.temp_file_name("save_joinedtable.dbf")
391            dbf = dbflib.create(dbffile)
392            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
393            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
394            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
395            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
396            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
397            dbf.close()
398    
399            # Create the session and a map
400            session = Session("A Joined Table session")
401            try:
402                map = Map("Test Map")
403                session.AddMap(map)
404    
405                # Add the dbf file to the session
406                dbftable = session.AddTable(DBFTable(dbffile))
407    
408                # Create a layer with the shapefile to use in the join
409                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
410                                       os.pardir, "Data", "iceland",
411                                       "roads-line.shp")
412                layer = Layer("My Layer", session.OpenShapefile(shpfile))
413                map.AddLayer(layer)
414    
415                # Do the join
416                store = layer.ShapeStore()
417                #for col in store.Table().Columns():
418                #    print col.name
419                joined = TransientJoinedTable(session.TransientDB(),
420                                              store.Table(), "RDLNTYPE",
421                                              dbftable, "RDTYPE",
422                                              outer_join = True)
423                store = session.AddShapeStore(DerivedShapeStore(store, joined))
424                layer.SetShapeStore(store)
425    
426                # Save the session
427                filename = self.temp_file_name("save_joinedtable.thuban")
428                save_session(session, filename)
429    
430                # Read it back and compare
431                file = open(filename)
432                written_contents = file.read()
433                file.close()
434                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
435                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
436                <session title="A Joined Table session"
437                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd">
438                    <fileshapesource filename="%(shpfile)s"
439                                     filetype="shapefile" id="D142197204"/>
440                    <filetable filename="%(dbffile)s"
441                               title="save_joinedtable"
442                               filetype="DBF" id="D141881756"/>
443                    <jointable id="D142180284"
444                               title="Join of roads-line and save_joinedtable"
445                               leftcolumn="RDLNTYPE" left="D142197204"
446                               rightcolumn="RDTYPE" right="D141881756"
447                               jointype="LEFT OUTER" />
448                    <derivedshapesource id="D141915644"
449                                        table="D142180284"
450                                        shapesource="D142197204"/>
451                    <map title="Test Map">
452                        <layer title="My Layer"
453                               shapestore="D141915644" visible="true"
454                               stroke="#000000" stroke_width="1" fill="None"/>
455                    </map>
456                </session>'''
457    
458                expected_contents = expected_template % {
459                    "dbffile": relative_filename(self.temp_dir(), dbffile),
460                    "shpfile": relative_filename(self.temp_dir(), shpfile)
461                    }
462                self.compare_xml(written_contents, expected_contents)
463            finally:
464                session.Destroy()
465                session = None
466    
467    
468    class MockDataStore:
469    
470        """A very simple data store that only has dependencies"""
471    
472        def __init__(self, name, *dependencies):
473            self.name = name
474            self.dependencies = dependencies
475    
476        def __repr__(self):
477            return self.name
478    
479        def Dependencies(self):
480            return self.dependencies
481    
482    
483    class TestStoreSort(unittest.TestCase):
484    
485        def check_sort(self, containers, sorted):
486            """Check whether the list of data containers is sorted"""
487            # check whether sorted is in the right order
488            seen = {}
489            for container in sorted:
490                self.failIf(id(container) in seen,
491                            "Container %r at least twice in %r" % (container,
492                                                                   sorted))
493                for dep in container.Dependencies():
494                    self.assert_(id(dep) in seen,
495                                 "Dependency %r of %r not yet seen" % (dep,
496                                                                       container))
497                seen[id(container)] = 1
498            # check whether all of containers is in sorted
499            for container in containers:
500                self.assert_(id(container) in seen,
501                             "Container %r in containers but not in sorted")
502            self.assertEquals(len(containers), len(sorted))
503    
504        def test_sort_data_stores(self):
505            """Test Thuban.Model.save.sort_data_stores"""
506            d1 = MockDataStore("d1")
507            d2 = MockDataStore("d2")
508            d3 = MockDataStore("d3", d1)
509            d4 = MockDataStore("d4", d1, d3)
510    
511            containers = [d4, d1, d2, d3]
512            self.check_sort(containers, sort_data_stores(containers))
513            containers = [d1, d3, d2, d4]
514            self.check_sort(containers, sort_data_stores(containers))
515    
516    
517    
518  if __name__ == "__main__":  if __name__ == "__main__":
519      # 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.1245  
changed lines
  Added in v.1452

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26