| Index: grit/grd_reader.py
|
| ===================================================================
|
| --- grit/grd_reader.py (revision 0)
|
| +++ grit/grd_reader.py (revision 0)
|
| @@ -0,0 +1,176 @@
|
| +#!/usr/bin/python2.4
|
| +# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +'''Class for reading GRD files into memory, without processing them.
|
| +'''
|
| +
|
| +import os.path
|
| +import types
|
| +import xml.sax
|
| +import xml.sax.handler
|
| +
|
| +from grit import exception
|
| +from grit.node import base
|
| +from grit.node import mapping
|
| +from grit.node import misc
|
| +from grit import util
|
| +
|
| +
|
| +class StopParsingException(Exception):
|
| + '''An exception used to stop parsing.'''
|
| + pass
|
| +
|
| +
|
| +class GrdContentHandler(xml.sax.handler.ContentHandler):
|
| + def __init__(self,
|
| + stop_after=None, debug=False, defines=None, tags_to_ignore=None):
|
| + # Invariant of data:
|
| + # 'root' is the root of the parse tree being created, or None if we haven't
|
| + # parsed out any elements.
|
| + # 'stack' is the a stack of elements that we push new nodes onto and
|
| + # pop from when they finish parsing, or [] if we are not currently parsing.
|
| + # 'stack[-1]' is the top of the stack.
|
| + self.root = None
|
| + self.stack = []
|
| + self.stop_after = stop_after
|
| + self.debug = debug
|
| + self.defines = defines
|
| + self.tags_to_ignore = tags_to_ignore or set()
|
| + self.ignore_depth = 0
|
| +
|
| + def startElement(self, name, attrs):
|
| + assert not self.root or len(self.stack) > 0
|
| +
|
| + if name in self.tags_to_ignore:
|
| + self.ignore_depth += 1
|
| + if self.debug:
|
| + print "Ignoring element %s and its children" % name
|
| +
|
| + if self.ignore_depth != 0:
|
| + return
|
| +
|
| + if self.debug:
|
| + attr_list = []
|
| + for attr in attrs.getNames():
|
| + attr_list.append('%s="%s"' % (attr, attrs.getValue(attr)))
|
| + if len(attr_list) == 0: attr_list = ['(none)']
|
| + attr_list = ' '.join(attr_list)
|
| + print ("Starting parsing of element %s with attributes %r" %
|
| + (name, attr_list))
|
| +
|
| + typeattr = None
|
| + if 'type' in attrs.getNames():
|
| + typeattr = attrs.getValue('type')
|
| +
|
| + node = mapping.ElementToClass(name, typeattr)()
|
| +
|
| + if not self.root:
|
| + self.root = node
|
| + if self.defines:
|
| + self.root.SetDefines(self.defines)
|
| +
|
| + if len(self.stack) > 0:
|
| + self.stack[-1].AddChild(node)
|
| + node.StartParsing(name, self.stack[-1])
|
| + else:
|
| + node.StartParsing(name, None)
|
| +
|
| + # Push
|
| + self.stack.append(node)
|
| +
|
| + for attr in attrs.getNames():
|
| + node.HandleAttribute(attr, attrs.getValue(attr))
|
| +
|
| + def endElement(self, name):
|
| + if self.ignore_depth == 0:
|
| + if self.debug:
|
| + print "End parsing of element %s" % name
|
| + # Pop
|
| + self.stack[-1].EndParsing()
|
| + assert len(self.stack) > 0
|
| + self.stack = self.stack[:-1]
|
| + if self.stop_after and name == self.stop_after:
|
| + raise StopParsingException()
|
| +
|
| + if name in self.tags_to_ignore:
|
| + self.ignore_depth -= 1
|
| +
|
| + def characters(self, content):
|
| + if self.ignore_depth == 0:
|
| + if self.stack[-1]:
|
| + self.stack[-1].AppendContent(content)
|
| +
|
| + def ignorableWhitespace(self, whitespace):
|
| + # TODO(joi) This is not supported by expat. Should use a different XML parser?
|
| + pass
|
| +
|
| +
|
| +def Parse(filename_or_stream, dir=None, flexible_root=False,
|
| + stop_after=None, debug=False, first_id_filename=None,
|
| + defines=None, tags_to_ignore=None):
|
| + '''Parses a GRD file into a tree of nodes (from grit.node).
|
| +
|
| + If flexible_root is False, the root node must be a <grit> element. Otherwise
|
| + it can be any element. The "own" directory of the file will only be fixed up
|
| + if the root node is a <grit> element.
|
| +
|
| + 'dir' should point to the directory of the input file, or be the full path
|
| + to the input file (the filename will be stripped).
|
| +
|
| + If 'stop_after' is provided, the parsing will stop once the first node
|
| + with this name has been fully parsed (including all its contents).
|
| +
|
| + If 'debug' is true, lots of information about the parsing events will be
|
| + printed out during parsing of the file.
|
| +
|
| + If first_id_filename is provided, then we use the provided path instead of
|
| + resources_id to gather the first id values for resources.
|
| +
|
| + Args:
|
| + filename_or_stream: './bla.xml' (must be filename if dir is None)
|
| + dir: '.' or None (only if filename_or_stream is a filename)
|
| + flexible_root: True | False
|
| + stop_after: 'inputs'
|
| + debug: False
|
| + first_id_filename: None
|
| + defines: dictionary of defines, like {'chromeos': '1'}
|
| +
|
| + Return:
|
| + Subclass of grit.node.base.Node
|
| +
|
| + Throws:
|
| + grit.exception.Parsing
|
| + '''
|
| + handler = GrdContentHandler(stop_after=stop_after, debug=debug,
|
| + defines=defines, tags_to_ignore=tags_to_ignore)
|
| + try:
|
| + xml.sax.parse(filename_or_stream, handler)
|
| + except StopParsingException:
|
| + assert stop_after
|
| + pass
|
| + except:
|
| + if not debug:
|
| + print "parse exception: run GRIT with the -x flag to debug .grd problems"
|
| + raise
|
| +
|
| + if not flexible_root or hasattr(handler.root, 'SetOwnDir'):
|
| + assert isinstance(filename_or_stream, types.StringType) or dir != None
|
| + if not dir:
|
| + dir = util.dirname(filename_or_stream)
|
| + if len(dir) == 0:
|
| + dir = '.'
|
| + # Fix up the base_dir so it is relative to the input file.
|
| + handler.root.SetOwnDir(dir)
|
| +
|
| + # Assign first ids to the nodes that don't have them.
|
| + if isinstance(handler.root, misc.GritNode) and first_id_filename != '':
|
| + handler.root.AssignFirstIds(filename_or_stream, first_id_filename, defines)
|
| +
|
| + return handler.root
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + util.ChangeStdoutEncoding()
|
| + print unicode(Parse(sys.argv[1]))
|
|
|
| Property changes on: grit/grd_reader.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|