/[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 1357 by jonathan, Wed Jul 2 09:38:27 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2002 by Intevation GmbH  # Copyright (c) 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 21  import xml.sax Line 21  import xml.sax
21  import xml.sax.handler  import xml.sax.handler
22  from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException  from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
23    
24    import xmlsupport
25    
26  import support  import support
27  support.initthuban()  support.initthuban()
28    
29  from Thuban.Model.save import 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  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  class SaxEventLister(xml.sax.handler.ContentHandler):  from Thuban.Model.data import DerivedShapeStore
40    
41      def __init__(self):  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
42          self.eventlist = []      ClassGroupProperties
43    
44      def startElementNS(self, name, qname, attrs):  from Thuban.Model.range import Range
45          items = attrs.items()  
46          items.sort()  
47          self.eventlist.append(("start", name, qname, items))  class XMLWriterTest(unittest.TestCase):
48    
49      def endElementNS(self, name, qname):      def testEncode(self):
50          self.eventlist.append(("end", name, qname))          """Test XMLWriter.encode"""
51            writer = XMLWriter()
52            eq = self.assertEquals
53  def sax_eventlist(data):  
54      """Return a list of SAX event generated for the XML data.          eq(writer.encode("hello world"), "hello world")
55      """          eq(writer.encode(unicode("hello world")), unicode("hello world"))
56      handler = SaxEventLister()  
57      parser = make_parser()          eq(writer.encode("\x80\x90\xc2\x100"),
58      parser.setContentHandler(handler)                           "\xc2\x80\xc2\x90\xc3\x82\x100")
59      parser.setErrorHandler(ErrorHandler())          eq(writer.encode(u"\x80\x90\xc2\x100"),
60      parser.setFeature(xml.sax.handler.feature_namespaces, 1)                           "\xc2\x80\xc2\x90\xc3\x82\x100")
61            eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
62      #  
63      # see comment at the end of Thuban/Model/load.py          eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
64      #          eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
65      try:  
66          parser.setFeature(xml.sax.handler.feature_validation, 0)  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
67          parser.setFeature(xml.sax.handler.feature_external_ges, 0)                        xmlsupport.ValidationTest):
68          parser.setFeature(xml.sax.handler.feature_external_pes, 0)  
69      except SAXNotRecognizedException:      dtd = "http://thuban.intevation.org/dtds/thuban-0.8.dtd"
70          pass      thubanids = [((dtd, n), (None, "id")) for n in
71                     ["fileshapesource", "filetable", "jointable",
72      inpsrc = xml.sax.InputSource()                    "derivedshapesource"]]
73      inpsrc.setByteStream(StringIO(data))      thubanidrefs = [((dtd, n), (None, m)) for n, m in
74      parser.parse(inpsrc)                      [("layer", "shapestore"),
75                         ("jointable", "left"),
76      return handler.eventlist                       ("jointable", "right"),
77                         ("derivedshapesource", "table"),
78  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):                       ("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))          if 0:
83                for a, b in zip(sax_eventlist(xml1, self.thubanids,
84                                            self.thubanidrefs),
85                              sax_eventlist(xml2, self.thubanids,
86                                            self.thubanidrefs)):
87                  print a == b and ' ' or '*****'
88                  print a
89                  print b
90            self.assertEquals(xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
91                                                       idrefs = self.thubanidrefs),
92                              xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
93                                                       idrefs = self.thubanidrefs))
94    
95      def testEmptySession(self):      def testEmptySession(self):
96          """Save an empty session"""          """Save an empty session"""
# Line 87  class SaveSessionTest(unittest.TestCase, Line 104  class SaveSessionTest(unittest.TestCase,
104          file.close()          file.close()
105          self.compare_xml(written_contents,          self.compare_xml(written_contents,
106                           '<?xml version="1.0" encoding="UTF-8"?>\n'                           '<?xml version="1.0" encoding="UTF-8"?>\n'
107                           '<!DOCTYPE session SYSTEM "thuban.dtd">\n'                           '<!DOCTYPE session SYSTEM "thuban-0.8.dtd">\n'
108                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
109             'xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">'
110                             '\n</session>\n')
111    
112            self.validate_data(written_contents)
113    
114      def testSingleLayer(self):      def testSingleLayer(self):
115          """Save a session with a single map with a single layer"""          """Save a session with a single map with a single layer"""
# Line 100  class SaveSessionTest(unittest.TestCase, Line 121  class SaveSessionTest(unittest.TestCase,
121          # use shapefile from the example data          # use shapefile from the example data
122          shpfile = os.path.join(os.path.dirname(__file__),          shpfile = os.path.join(os.path.dirname(__file__),
123                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
124          layer = Layer("My Layer", shpfile)          layer = Layer("My Layer", session.OpenShapefile(shpfile))
125          map.AddLayer(layer)          map.AddLayer(layer)
126    
127          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_singlemap.thuban")
128          save_session(session, filename)          save_session(session, filename)
129    
130            file = open(filename)
131            written_contents = file.read()
132            file.close()
133            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
134            <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
135            <session title="single map&amp;layer"
136               xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
137                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
138                <map title="Test Map">
139                    <projection name="Unknown">
140                        <parameter value="zone=26"/>
141                        <parameter value="proj=utm"/>
142                        <parameter value="ellps=clrk66"/>
143                    </projection>
144                    <layer title="My Layer" shapestore="D1"
145                    fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
146                </map>
147            </session>'''
148    
149            expected_contents = expected_template % \
150                (os.path.join("..", "..", "Data", "iceland", "political.shp"),
151                 "true")
152    
153            self.compare_xml(written_contents, expected_contents)
154    
155            self.validate_data(written_contents)
156    
157            layer.SetVisible(False)
158            save_session(session, filename)
159    
160            file = open(filename)
161            written_contents = file.read()
162            file.close()
163            expected_contents = expected_template % \
164                (os.path.join("..", "..", "Data", "iceland", "political.shp"),
165                 "false")
166            self.compare_xml(written_contents, expected_contents)
167            self.validate_data(written_contents)
168    
169            session.Destroy()
170    
171        def testLayerProjection(self):
172            """Test saving layers with projections"""
173            # deliberately put an apersand in the title :)
174            session = Session("single map&layer")
175            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
176            map = Map("Test Map", projection = proj)
177            session.AddMap(map)
178            # use shapefile from the example data
179            shpfile = os.path.join(os.path.dirname(__file__),
180                                   os.pardir, "Data", "iceland", "political.shp")
181            layer = Layer("My Layer", session.OpenShapefile(shpfile))
182            proj = Projection(["proj=lcc", "ellps=clrk66"], "Layer Projection")
183            layer.SetProjection(proj)
184            map.AddLayer(layer)
185    
186            filename = self.temp_file_name("save_layerproj.thuban")
187            save_session(session, filename)
188          session.Destroy()          session.Destroy()
189    
190          file = open(filename)          file = open(filename)
191          written_contents = file.read()          written_contents = file.read()
192          file.close()          file.close()
193          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
194          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
195          <session title="single map&amp;layer">          <session title="single map&amp;layer"
196               xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
197                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
198              <map title="Test Map">              <map title="Test Map">
199                  <projection>                  <projection name="Unknown">
200                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
201                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
202                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
203                  </projection>                  </projection>
204                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
205                  fill="None" stroke="#000000" stroke_width="1"/>                  fill="None" stroke="#000000" stroke_width="1" visible="true">
206                        <projection name="Layer Projection">
207                            <parameter value="proj=lcc"/>
208                            <parameter value="ellps=clrk66"/>
209                        </projection>
210                    </layer>
211              </map>              </map>
212          </session>''' % os.path.join("..", "..", "Data", "iceland",          </session>''' % os.path.join("..", "..", "Data", "iceland",
213                                       "political.shp")                                       "political.shp")
# Line 129  class SaveSessionTest(unittest.TestCase, Line 216  class SaveSessionTest(unittest.TestCase,
216          #print expected_contents          #print expected_contents
217          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
218    
219            self.validate_data(written_contents)
220    
221        def testRasterLayer(self):
222            # deliberately put an apersand in the title :)
223            session = Session("single map&layer")
224            map = Map("Test Map")
225            session.AddMap(map)
226            # use shapefile from the example data
227            imgfile = os.path.join(os.path.dirname(__file__),
228                                   os.pardir, "Data", "iceland", "island.tif")
229            layer = RasterLayer("My RasterLayer", imgfile)
230            map.AddLayer(layer)
231    
232            filename = self.temp_file_name("save_singlemap.thuban")
233            save_session(session, filename)
234            session.Destroy()
235    
236            file = open(filename)
237            written_contents = file.read()
238            file.close()
239            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
240            <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
241            <session title="single map&amp;layer"
242               xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
243                <map title="Test Map">
244                    <rasterlayer title="My RasterLayer" filename="%s"
245                                 visible="true">
246                    </rasterlayer>
247                </map>
248            </session>''' % os.path.join(os.path.dirname(__file__),
249                                         os.pardir, "Data", "iceland",
250                                         "island.tif")
251            #print written_contents
252            #print "********************************************"
253            #print expected_contents
254            self.compare_xml(written_contents, expected_contents)
255    
256            self.validate_data(written_contents)
257    
258        def testClassifiedLayer(self):
259            """Save a session with a single map with a single layer
260               with a classificaton.
261            """
262            # deliberately put an apersand in the title :)
263            session = Session("single map&layer")
264            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
265            map = Map("Test Map", projection = proj)
266            session.AddMap(map)
267            # use shapefile from the example data
268            shpfile = os.path.join(os.path.dirname(__file__),
269                                   os.pardir, "Data", "iceland", "political.shp")
270            layer = Layer("My Layer", session.OpenShapefile(shpfile))
271            map.AddLayer(layer)
272    
273            clazz = layer.GetClassification()
274    
275            clazz.SetFieldInfo("AREA", None)
276    
277            clazz.AppendGroup(ClassGroupSingleton(42,
278                                               ClassGroupProperties(),
279                                               "single"))
280            clazz.AppendGroup(ClassGroupSingleton("text",
281                                               ClassGroupProperties(),
282                                               "single-text"))
283    
284            clazz.AppendGroup(ClassGroupRange((0, 42),
285                                               ClassGroupProperties(),
286                                               "range"))
287    
288            range = ClassGroupRange(Range("[0;42]"))
289            range.SetProperties(ClassGroupProperties())
290            range.SetLabel("new-range")
291            clazz.AppendGroup(range)
292    
293            filename = self.temp_file_name("save_singlemap.thuban")
294            save_session(session, filename)
295    
296            file = open(filename)
297            written_contents = file.read()
298            file.close()
299            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
300            <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
301            <session title="single map&amp;layer"
302               xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
303                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
304                <map title="Test Map">
305                    <projection name="Unknown">
306                        <parameter value="zone=26"/>
307                        <parameter value="proj=utm"/>
308                        <parameter value="ellps=clrk66"/>
309                    </projection>
310                    <layer title="My Layer" shapestore="D1"
311                    fill="None" stroke="#000000" stroke_width="1" visible="%s">
312                        <classification field="AREA" field_type="double">
313                            <clnull label="">
314                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
315                            </clnull>
316                            <clpoint value="42" label="single">
317                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
318                            </clpoint>
319                            <clpoint value="text" label="single-text">
320                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
321                            </clpoint>
322                            <clrange range="[0;42[" label="range">
323                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
324                            </clrange>
325                            <clrange range="[0;42]" label="new-range">
326                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
327                            </clrange>
328                        </classification>
329                    </layer>
330                </map>
331            </session>'''
332    
333            expected_contents = expected_template % \
334                (os.path.join("..", "..", "Data", "iceland", "political.shp"),
335                 "true")
336    
337            #print written_contents
338            #print "********************************************"
339            #print expected_contents
340            self.compare_xml(written_contents, expected_contents)
341    
342            self.validate_data(written_contents)
343    
344            session.Destroy()
345    
346        def test_dbf_table(self):
347            """Test saving a session with a dbf table link"""
348            session = Session("a DBF Table session")
349            # use shapefile from the example data
350            dbffile = os.path.join(os.path.dirname(__file__),
351                                   os.pardir, "Data", "iceland", "political.dbf")
352            table = session.AddTable(DBFTable(dbffile))
353    
354            filename = self.temp_file_name("save_singletable.thuban")
355            save_session(session, filename)
356    
357            file = open(filename)
358            written_contents = file.read()
359            file.close()
360            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
361            <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
362            <session title="a DBF Table session"
363               xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
364                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
365            </session>'''
366    
367            expected_contents = expected_template % dbffile
368            self.compare_xml(written_contents, expected_contents)
369    
370        def test_joined_table(self):
371            """Test saving a session with joined table"""
372            # Create a simple table to use in the join
373            dbffile = self.temp_file_name("save_joinedtable.dbf")
374            dbf = dbflib.create(dbffile)
375            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
376            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
377            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
378            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
379            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
380            dbf.close()
381    
382            # Create the session and a map
383            session = Session("A Joined Table session")
384            try:
385                map = Map("Test Map")
386                session.AddMap(map)
387    
388                # Add the dbf file to the session
389                dbftable = session.AddTable(DBFTable(dbffile))
390    
391                # Create a layer with the shapefile to use in the join
392                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
393                                       os.pardir, "Data", "iceland",
394                                       "roads-line.shp")
395                layer = Layer("My Layer", session.OpenShapefile(shpfile))
396                map.AddLayer(layer)
397    
398                # Do the join
399                store = layer.ShapeStore()
400                #for col in store.Table().Columns():
401                #    print col.name
402                joined = TransientJoinedTable(session.TransientDB(),
403                                              store.Table(), "RDLNTYPE",
404                                              dbftable, "RDTYPE")
405                store = session.AddShapeStore(DerivedShapeStore(store, joined))
406                layer.SetShapeStore(store)
407    
408                # Save the session
409                filename = self.temp_file_name("save_joinedtable.thuban")
410                save_session(session, filename)
411    
412                # Read it back and compare
413                file = open(filename)
414                written_contents = file.read()
415                file.close()
416                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
417                <!DOCTYPE session SYSTEM "thuban-0.8.dtd">
418                <session title="A Joined Table session"
419                 xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd">
420                    <fileshapesource filename="%(shpfile)s"
421                                     filetype="shapefile" id="D142197204"/>
422                    <filetable filename="%(dbffile)s"
423                               title="save_joinedtable"
424                               filetype="DBF" id="D141881756"/>
425                    <jointable id="D142180284"
426                               title="Join of roads-line and save_joinedtable"
427                               leftcolumn="RDLNTYPE" left="D142197204"
428                               rightcolumn="RDTYPE" right="D141881756"/>
429                    <derivedshapesource id="D141915644"
430                                        table="D142180284"
431                                        shapesource="D142197204"/>
432                    <map title="Test Map">
433                        <layer title="My Layer"
434                               shapestore="D141915644" visible="true"
435                               stroke="#000000" stroke_width="1" fill="None"/>
436                    </map>
437                </session>'''
438    
439                expected_contents = expected_template % {
440                    "dbffile": relative_filename(self.temp_dir(), dbffile),
441                    "shpfile": relative_filename(self.temp_dir(), shpfile)
442                    }
443                self.compare_xml(written_contents, expected_contents)
444            finally:
445                session.Destroy()
446                session = None
447    
448    
449    class MockDataStore:
450    
451        """A very simple data store that only has dependencies"""
452    
453        def __init__(self, name, *dependencies):
454            self.name = name
455            self.dependencies = dependencies
456    
457        def __repr__(self):
458            return self.name
459    
460        def Dependencies(self):
461            return self.dependencies
462    
463    
464    class TestStoreSort(unittest.TestCase):
465    
466        def check_sort(self, containers, sorted):
467            """Check whether the list of data containers is sorted"""
468            # check whether sorted is in the right order
469            seen = {}
470            for container in sorted:
471                self.failIf(id(container) in seen,
472                            "Container %r at least twice in %r" % (container,
473                                                                   sorted))
474                for dep in container.Dependencies():
475                    self.assert_(id(dep) in seen,
476                                 "Dependency %r of %r not yet seen" % (dep,
477                                                                       container))
478                seen[id(container)] = 1
479            # check whether all of containers is in sorted
480            for container in containers:
481                self.assert_(id(container) in seen,
482                             "Container %r in containers but not in sorted")
483            self.assertEquals(len(containers), len(sorted))
484    
485        def test_sort_data_stores(self):
486            """Test Thuban.Model.save.sort_data_stores"""
487            d1 = MockDataStore("d1")
488            d2 = MockDataStore("d2")
489            d3 = MockDataStore("d3", d1)
490            d4 = MockDataStore("d4", d1, d3)
491    
492            containers = [d4, d1, d2, d3]
493            self.check_sort(containers, sort_data_stores(containers))
494            containers = [d1, d3, d2, d4]
495            self.check_sort(containers, sort_data_stores(containers))
496    
497    
498    
499  if __name__ == "__main__":  if __name__ == "__main__":
500      # Fake the __file__ global because it's needed by a test      # Fake the __file__ global because it's needed by a test
501      import sys      import sys
502      __file__ = sys.argv[0]      __file__ = sys.argv[0]
503      unittest.main()      support.run_tests()

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26