/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/load.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/load.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 694 by jonathan, Wed Apr 16 16:39:18 2003 UTC revision 1268 by bh, Fri Jun 20 16:10:12 2003 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001, 2002 by Intevation GmbH  # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
# Line 13  Parser for thuban session files. Line 13  Parser for thuban session files.
13    
14  __version__ = "$Revision$"  __version__ = "$Revision$"
15    
16  import sys, string, os  import string, os
17    
18  import xml.sax  import xml.sax
19  import xml.sax.handler  import xml.sax.handler
20  from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException  from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
21    
22  from Thuban import _  from Thuban import _
 from Thuban.common import *  
23    
24  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
25       FIELDTYPE_STRING       FIELDTYPE_STRING
26    
27  from Thuban.Model.session import Session  from Thuban.Model.session import Session
28  from Thuban.Model.map import Map  from Thuban.Model.map import Map
29  from Thuban.Model.layer import Layer  from Thuban.Model.layer import Layer, RasterLayer
30  from Thuban.Model.color import Color  from Thuban.Model.color import Color
31  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
32    from Thuban.Model.range import Range
33  from Thuban.Model.classification import Classification, \  from Thuban.Model.classification import Classification, \
34      ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \      ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
35      ClassGroupProperties      ClassGroupProperties
36    from Thuban.Model.data import DerivedShapeStore, ShapefileStore
37    from Thuban.Model.table import DBFTable
38    from Thuban.Model.transientdb import TransientJoinedTable
39    
40    class LoadError(Exception):
41        pass
42    
43    from Thuban.Model.xmlreader import XMLReader
44    import resource
45    
46  def parse_color(color):  def parse_color(color):
47      """Return the color object for the string color.      """Return the color object for the string color.
# Line 57  def parse_color(color): Line 65  def parse_color(color):
65          raise ValueError(_("Invalid color specification %s") % color)          raise ValueError(_("Invalid color specification %s") % color)
66      return result      return result
67    
68    class AttrDesc:
69    
70  class XMLProcessor(xml.sax.handler.ContentHandler):      def __init__(self, name, required = False, default = "",
71                     conversion = None):
72      # Dictionary mapping element names (or (URI, element name) pairs for          if not isinstance(name, tuple):
73      # documents using namespaces) to method names. The methods should              fullname = (None, name)
     # accept the same parameters as the startElement (or startElementNS)  
     # methods. The start_dispatcher is used by the default startElement  
     # and startElementNS methods to call a method for the open tag of an  
     # element.  
     start_dispatcher = {}  
   
     # end_dispatcher works just like start_dispatcher but it's used by  
     # endElement and endElementNS. The method whose names it maps to  
     # should accept the same parameters as endElement and endElementNS.  
     end_dispatcher = {}  
   
   
     def __init__(self, directory):  
         """Inititialize the Sax handler.  
   
         The directory parameter should be the directory containing the  
         session file. It's needed to interpret embedded relative  
         filenames.  
         """  
         self.directory = directory  
         self.chars = ''  
   
     def startElementNS(self, name, qname, attrs):  
         """Call the method given for name in self.start_dispatcher  
         """  
         if name[0] is None:  
             method_name = self.start_dispatcher.get(name[1])  
74          else:          else:
75              # Dispatch with namespace              fullname = name
76              method_name = self.start_dispatcher.get(name)              name = name[1]
77          if method_name is not None:          self.name = name
78              getattr(self, method_name)(name, qname, attrs)          self.fullname = fullname
79            self.required = required
80            self.default = default
81            self.conversion = conversion
82    
83      def endElementNS(self, name, qname):          # set by the SessionLoader's check_attrs method
84          """Call the method given for name in self.end_dispatcher          self.value = None
         """  
         if name[0] is None:  
             method_name = self.end_dispatcher.get(name[1])  
         else:  
             # Dispatch with namespace  
             method_name = self.end_dispatcher.get(name)  
         if method_name is not None:  
             getattr(self, method_name)(name, qname)  
85    
     def GetDirectory(self):  
         return self.directory  
86    
87  class ProcessSession(XMLProcessor):  class SessionLoader(XMLReader):
88    
89      def __init__(self, directory):      def __init__(self):
90          """Inititialize the Sax handler."""          """Inititialize the Sax handler."""
91          XMLProcessor.__init__(self, directory)          XMLReader.__init__(self)
92    
93          self.theSession = None          self.theSession = None
94          self.aMap = None          self.aMap = None
95          self.aLayer = None          self.aLayer = None
96    
97            # Map ids used in the thuban file to the corresponding objects
98            # in the session
99            self.idmap = {}
100    
101            dispatchers = {
102                'session'       : ("start_session",        "end_session"),
103                'fileshapesource': ("start_fileshapesource", None),
104                'derivedshapesource': ("start_derivedshapesource", None),
105                'filetable': ("start_filetable", None),
106                'jointable': ("start_jointable", None),
107    
108                'map'           : ("start_map",            "end_map"),
109                'projection'    : ("start_projection",     "end_projection"),
110                'parameter'     : ("start_parameter",      None),
111                'layer'         : ("start_layer",          "end_layer"),
112                'rasterlayer'   : ("start_rasterlayer",    "end_rasterlayer"),
113                'classification': ("start_classification", "end_classification"),
114                'clnull'        : ("start_clnull",         "end_clnull"),
115                'clpoint'       : ("start_clpoint",        "end_clpoint"),
116                'clrange'       : ("start_clrange",        "end_clrange"),
117                'cldata'        : ("start_cldata",         "end_cldata"),
118                'table'         : ("start_table",          "end_table"),
119                'labellayer'    : ("start_labellayer",     None),
120                'label'         : ("start_label",          None)}
121    
122            # all dispatchers should be used for the 0.8 namespace
123            xmlns = "http://thuban.intevation.org/dtds/thuban-0.8.dtd"
124            for key, value in dispatchers.items():
125                dispatchers[(xmlns, key)] = value
126    
127            XMLReader.AddDispatchers(self, dispatchers)
128    
129      def start_session(self, name, qname, attrs):      def start_session(self, name, qname, attrs):
130          self.theSession = Session(attrs.get((None, 'title'), None))          self.theSession = Session(self.encode(attrs.get((None, 'title'),
131      XMLProcessor.start_dispatcher['session'] = "start_session"                                                          None)))
132    
133      def end_session(self, name, qname):      def end_session(self, name, qname):
134          pass          pass
135      XMLProcessor.end_dispatcher['session'] = "end_session"  
136        def check_attrs(self, element, attrs, descr):
137            """Check and convert some of the attributes of an element
138    
139            Parameters:
140               element -- The element name
141               attrs -- The attrs mapping as passed to the start_* methods
142               descr -- Sequence of attribute descriptions (AttrDesc instances)
143    
144            Return a dictionary containig normalized versions of the
145            attributes described in descr. The keys of that dictionary are
146            the name attributes of the attribute descriptions. The attrs
147            dictionary will not be modified.
148    
149            If the attribute is required, i.e. the 'required' attribute of
150            the descrtiption is true, but it is not in attrs, raise a
151            LoadError.
152    
153            If the attribute has a default value and it is not present in
154            attrs, use that default value as the value in the returned dict.
155    
156            If a conversion is specified, convert the value before putting
157            it into the returned dict. The following conversions are
158            available:
159    
160               'filename' -- The attribute is a filename.
161    
162                             If the filename is a relative name, interpret
163                             it relative to the directory containing the
164                             .thuban file and make it an absolute name
165    
166               'shapestore' -- The attribute is the ID of a shapestore
167                               defined earlier in the .thuban file. Look it
168                               up self.idmap
169    
170               'table' -- The attribute is the ID of a table or shapestore
171                          defined earlier in the .thuban file. Look it up
172                          self.idmap. If it's the ID of a shapestore the
173                          value will be the table of the shapestore.
174            """
175            normalized = {}
176    
177            for d in descr:
178                if d.required and not attrs.has_key(d.fullname):
179                    pass
180                #raise LoadError("Element %s requires an attribute %r"
181                #                    % (element, d.name))
182                value = attrs.get(d.fullname, d.default)
183    
184                if d.conversion == "shapesource":
185                    if value in self.idmap:
186                        value = self.idmap[value]
187                    else:
188                        raise LoadError("Element %s requires an already defined ID"
189                                        " in attribute %r"
190                                        % (element, d.name))
191                elif d.conversion == "table":
192                    if value in self.idmap:
193                        value = self.idmap[value]
194                        if isinstance(value, ShapefileStore):
195                            value = value.Table()
196                    else:
197                        raise LoadError("Element %s requires an already defined ID"
198                                        " in attribute %r"
199                                        % (element, d.name))
200                elif d.conversion == "filename":
201                    value = os.path.abspath(os.path.join(self.GetDirectory(),
202                                                         value))
203    
204                normalized[d.name] = value
205            return normalized
206    
207        def start_fileshapesource(self, name, qname, attrs):
208            attrs = self.check_attrs(name, attrs,
209                                      [AttrDesc("id", True),
210                                       AttrDesc("filename", True,
211                                                conversion = "filename"),
212                                       AttrDesc("filetype", True)])
213            ID = attrs["id"]
214            filename = attrs["filename"]
215            filetype = attrs["filetype"]
216            if filetype != "shapefile":
217                raise LoadError("shapesource filetype %r not supported" % filetype)
218            self.idmap[ID] = self.theSession.OpenShapefile(filename)
219    
220        def start_derivedshapesource(self, name, qname, attrs):
221            attrs = self.check_attrs(name, attrs,
222                                     [AttrDesc("id", True),
223                                      AttrDesc("shapesource", True,
224                                               conversion = "shapesource"),
225                                      AttrDesc("table", True, conversion="table")])
226            self.idmap[attrs["id"]] = DerivedShapeStore(attrs["shapesource"],
227                                                        attrs["table"])
228    
229        def start_filetable(self, name, qname, attrs):
230            attrs = self.check_attrs(name, attrs,
231                                     [AttrDesc("id", True),
232                                      AttrDesc("title", True),
233                                      AttrDesc("filename", True,
234                                               conversion = "filename"),
235                                      AttrDesc("filetype")])
236            filetype = attrs["filetype"]
237            if filetype != "DBF":
238                raise LoadError("shapesource filetype %r not supported" % filetype)
239            table = DBFTable(attrs["filename"])
240            table.SetTitle(attrs["title"])
241            self.idmap[attrs["id"]] = self.theSession.AddTable(table)
242    
243        def start_jointable(self, name, qname, attrs):
244            attrs = self.check_attrs(name, attrs,
245                                     [AttrDesc("id", True),
246                                      AttrDesc("title", True),
247                                      AttrDesc("left", True, conversion="table"),
248                                      AttrDesc("leftcolumn", True),
249                                      AttrDesc("right", True, conversion="table"),
250                                      AttrDesc("rightcolumn")])
251            table = TransientJoinedTable(self.theSession.TransientDB(),
252                                         attrs["left"], attrs["leftcolumn"],
253                                         attrs["right"], attrs["rightcolumn"])
254            table.SetTitle(attrs["title"])
255            self.idmap[attrs["id"]] = self.theSession.AddTable(table)
256    
257      def start_map(self, name, qname, attrs):      def start_map(self, name, qname, attrs):
258          """Start a map."""          """Start a map."""
259          self.aMap = Map(attrs.get((None, 'title'), None))          self.aMap = Map(attrs.get((None, 'title'), None))
     XMLProcessor.start_dispatcher['map'] = "start_map"  
260    
261      def end_map(self, name, qname):      def end_map(self, name, qname):
262          self.theSession.AddMap(self.aMap)          self.theSession.AddMap(self.aMap)
263      XMLProcessor.end_dispatcher['map'] = "end_map"          self.aMap = None
264    
265      def start_projection(self, name, qname, attrs):      def start_projection(self, name, qname, attrs):
266            self.ProjectionName = self.encode(attrs.get((None, 'name'), None))
267          self.ProjectionParams = [ ]          self.ProjectionParams = [ ]
     XMLProcessor.start_dispatcher['projection'] = "start_projection"  
268    
269      def end_projection(self, name, qname):      def end_projection(self, name, qname):
270          self.aMap.SetProjection(Projection(self.ProjectionParams))          if self.aLayer is not None:
271      XMLProcessor.end_dispatcher['projection'] = "end_projection"              obj = self.aLayer
272            elif self.aMap is not None:
273                obj = self.aMap
274            else:
275                assert False, "projection tag out of context"
276                pass
277    
278            obj.SetProjection(
279                Projection(self.ProjectionParams, self.ProjectionName))
280    
281      def start_parameter(self, name, qname, attrs):      def start_parameter(self, name, qname, attrs):
282          s = attrs.get((None, 'value'))          s = attrs.get((None, 'value'))
283          s = str(s) # we can't handle unicode in proj          s = str(s) # we can't handle unicode in proj
284          self.ProjectionParams.append(s)          self.ProjectionParams.append(s)
     XMLProcessor.start_dispatcher['parameter'] = "start_parameter"  
285    
286      def start_layer(self, name, qname, attrs, layer_class = Layer):      def start_layer(self, name, qname, attrs, layer_class = Layer):
287          """Start a layer          """Start a layer
# Line 157  class ProcessSession(XMLProcessor): Line 290  class ProcessSession(XMLProcessor):
290          attrs which may be a dictionary as well as the normal SAX attrs          attrs which may be a dictionary as well as the normal SAX attrs
291          object and bind it to self.aLayer.          object and bind it to self.aLayer.
292          """          """
293          title = attrs.get((None, 'title'), "")          title = self.encode(attrs.get((None, 'title'), ""))
294          filename = attrs.get((None, 'filename'), "")          filename = attrs.get((None, 'filename'), "")
295          filename = os.path.join(self.GetDirectory(), filename)          filename = os.path.join(self.GetDirectory(), filename)
296            filename = self.encode(filename)
297            visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"
298          fill = parse_color(attrs.get((None, 'fill'), "None"))          fill = parse_color(attrs.get((None, 'fill'), "None"))
299          stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))          stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
300          stroke_width = int(attrs.get((None, 'stroke_width'), "1"))          stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
301          self.aLayer = layer_class(title, filename, fill = fill,          if attrs.has_key((None, "shapestore")):
302                                    stroke = stroke, lineWidth = stroke_width)              store = self.idmap[attrs[(None, "shapestore")]]
303      XMLProcessor.start_dispatcher['layer'] = "start_layer"          else:
304                store = self.theSession.OpenShapefile(filename)
305            self.aLayer = layer_class(title, store,
306                                      fill = fill, stroke = stroke,
307                                      lineWidth = stroke_width,
308                                      visible = visible)
309    
310      def end_layer(self, name, qname):      def end_layer(self, name, qname):
311          self.aMap.AddLayer(self.aLayer)          self.aMap.AddLayer(self.aLayer)
312      XMLProcessor.end_dispatcher['layer'] = "end_layer"          self.aLayer = None
313    
314        def start_rasterlayer(self, name, qname, attrs, layer_class = RasterLayer):
315            title = self.encode(attrs.get((None, 'title'), ""))
316            filename = attrs.get((None, 'filename'), "")
317            filename = os.path.join(self.GetDirectory(), filename)
318            filename = self.encode(filename)
319            visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"
320    
321            self.aLayer = layer_class(title, filename, visible = visible)
322    
323        def end_rasterlayer(self, name, qname):
324            self.aMap.AddLayer(self.aLayer)
325            self.aLayer = None
326    
327      def start_classification(self, name, qname, attrs):      def start_classification(self, name, qname, attrs):
328          field = attrs.get((None, 'field'), None)          field = attrs.get((None, 'field'), None)
# Line 191  class ProcessSession(XMLProcessor): Line 344  class ProcessSession(XMLProcessor):
344    
345          self.aLayer.GetClassification().SetField(field)          self.aLayer.GetClassification().SetField(field)
346    
     XMLProcessor.start_dispatcher['classification'] = "start_classification"  
   
347      def end_classification(self, name, qname):      def end_classification(self, name, qname):
348          pass          pass
     XMLProcessor.end_dispatcher['classification'] = "end_classification"  
349    
350      def start_clnull(self, name, qname, attrs):      def start_clnull(self, name, qname, attrs):
351          self.cl_group = ClassGroupDefault()          self.cl_group = ClassGroupDefault()
352          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))          self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
353          self.cl_prop = ClassGroupProperties()          self.cl_prop = ClassGroupProperties()
     XMLProcessor.start_dispatcher['clnull'] = "start_clnull"  
354    
355      def end_clnull(self, name, qname):      def end_clnull(self, name, qname):
356          self.cl_group.SetProperties(self.cl_prop)          self.cl_group.SetProperties(self.cl_prop)
357          self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)          self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
358          del self.cl_group, self.cl_prop          del self.cl_group, self.cl_prop
     XMLProcessor.end_dispatcher['clnull'] = "end_clnull"  
359    
360      def start_clpoint(self, name, qname, attrs):      def start_clpoint(self, name, qname, attrs):
361          attrib_value = attrs.get((None, 'value'), "0")          attrib_value = attrs.get((None, 'value'), "0")
362    
         #try:  
             #value  = Str2Num(attrib_value)  
         #except:  
             #value  = attrib_value  
   
363          value = self.conv(attrib_value)          value = self.conv(attrib_value)
364    
365          self.cl_group = ClassGroupSingleton(value)          self.cl_group = ClassGroupSingleton(value)
366          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))          self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
367          self.cl_prop = ClassGroupProperties()          self.cl_prop = ClassGroupProperties()
368    
     XMLProcessor.start_dispatcher['clpoint'] = "start_clpoint"  
369    
370      def end_clpoint(self, name, qname):      def end_clpoint(self, name, qname):
371          self.cl_group.SetProperties(self.cl_prop)          self.cl_group.SetProperties(self.cl_prop)
372          self.aLayer.GetClassification().AppendGroup(self.cl_group)          self.aLayer.GetClassification().AppendGroup(self.cl_group)
373          del self.cl_group, self.cl_prop          del self.cl_group, self.cl_prop
     XMLProcessor.end_dispatcher['clpoint'] = "end_clpoint"  
374    
375      def start_clrange(self, name, qname, attrs):      def start_clrange(self, name, qname, attrs):
376    
377            range = attrs.get((None, 'range'), None)
378            # for backward compatibility (min/max are not saved)
379            min   = attrs.get((None, 'min'), None)
380            max   = attrs.get((None, 'max'), None)
381    
382          try:          try:
383              min = self.conv(attrs.get((None, 'min'), "0"))              if range is not None:
384              max = self.conv(attrs.get((None, 'max'), "0"))                  self.cl_group = ClassGroupRange(Range(range))
385              #min = Str2Num(attrs.get((None, 'min'), "0"))              elif min is not None and max is not None:
386              #max = Str2Num(attrs.get((None, 'max'), "0"))                  self.cl_group = ClassGroupRange(self.conv(min), self.conv(max))
387                else:
388                    self.cl_group = ClassGroupRange(Range(None))
389    
390          except ValueError:          except ValueError:
391              raise ValueError(_("Classification range is not a number!"))              raise ValueError(_("Classification range is not a number!"))
392    
         self.cl_group = ClassGroupRange(min, max)  
393          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
394          self.cl_prop = ClassGroupProperties()          self.cl_prop = ClassGroupProperties()
395    
     XMLProcessor.start_dispatcher['clrange'] = "start_clrange"  
396    
397      def end_clrange(self, name, qname):      def end_clrange(self, name, qname):
398          self.cl_group.SetProperties(self.cl_prop)          self.cl_group.SetProperties(self.cl_prop)
399          self.aLayer.GetClassification().AppendGroup(self.cl_group)          self.aLayer.GetClassification().AppendGroup(self.cl_group)
400          del self.cl_group, self.cl_prop          del self.cl_group, self.cl_prop
     XMLProcessor.end_dispatcher['clrange'] = "end_clrange"  
401    
402      def start_cldata(self, name, qname, attrs):      def start_cldata(self, name, qname, attrs):
403          self.cl_prop.SetLineColor(          self.cl_prop.SetLineColor(
# Line 259  class ProcessSession(XMLProcessor): Line 405  class ProcessSession(XMLProcessor):
405          self.cl_prop.SetLineWidth(          self.cl_prop.SetLineWidth(
406              int(attrs.get((None, 'stroke_width'), "0")))              int(attrs.get((None, 'stroke_width'), "0")))
407          self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))          self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
     XMLProcessor.start_dispatcher['cldata'] = "start_cldata"  
408    
409      def end_cldata(self, name, qname):      def end_cldata(self, name, qname):
410          pass          pass
     XMLProcessor.end_dispatcher['cldata'] = "end_cldata"  
   
     def start_table(self, name, qname, attrs):  
         #print "table title: %s" % attrs.get('title', None)  
         pass  
     XMLProcessor.start_dispatcher['table'] = "start_table"  
   
     def end_table(self, name, qname):  
         pass  
     XMLProcessor.end_dispatcher['table'] = "end_table"  
411    
412      def start_labellayer(self, name, qname, attrs):      def start_labellayer(self, name, qname, attrs):
413          self.aLayer = self.aMap.LabelLayer()          self.aLayer = self.aMap.LabelLayer()
     XMLProcessor.start_dispatcher['labellayer'] = "start_labellayer"  
414    
415      def start_label(self, name, qname, attrs):      def start_label(self, name, qname, attrs):
416          x = float(attrs[(None, 'x')])          x = float(attrs[(None, 'x')])
417          y = float(attrs[(None, 'y')])          y = float(attrs[(None, 'y')])
418          text = attrs[(None, 'text')]          text = self.encode(attrs[(None, 'text')])
419          halign = attrs[(None, 'halign')]          halign = attrs[(None, 'halign')]
420          valign = attrs[(None, 'valign')]          valign = attrs[(None, 'valign')]
421          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
     XMLProcessor.start_dispatcher['label'] = "start_label"  
422    
423      def characters(self, chars):      def characters(self, chars):
424          pass          pass
425    
426    
 def load_xmlfile(filename, handler):  
     file = open(filename)  
   
     parser = make_parser()  
     parser.setContentHandler(handler)  
     parser.setErrorHandler(ErrorHandler())  
     parser.setFeature(xml.sax.handler.feature_namespaces, 1)  
   
     #  
     # Well, this isn't pretty, but it appears that if you  
     # use Python 2.2 without the site-package _xmlplus then  
     # the following will fail, and without them it will work.  
     # However, if you do have the site-package and you don't  
     # call these functions, the reader raises an exception  
     #  
     # The reason we set these to 0 in the first place is  
     # because there is an unresolved issue with external  
     # entities causing an exception in the reader  
     #  
     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  
   
     parser.parse(file)  
   
427  def load_session(filename):  def load_session(filename):
428      """Load a Thuban session from the file object file"""      """Load a Thuban session from the file object file"""
429    
430      dir = os.path.dirname(filename)      handler = SessionLoader()
431      handler = ProcessSession(dir)      handler.read(filename)
   
     load_xmlfile(filename, handler)  
432    
433      session = handler.theSession      session = handler.theSession
434      # Newly loaded session aren't modified      # Newly loaded session aren't modified

Legend:
Removed from v.694  
changed lines
  Added in v.1268

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26