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

Legend:
Removed from v.494  
changed lines
  Added in v.1375

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26