| Index: grit/node/structure.py
 | 
| ===================================================================
 | 
| --- grit/node/structure.py	(revision 0)
 | 
| +++ grit/node/structure.py	(revision 0)
 | 
| @@ -0,0 +1,263 @@
 | 
| +#!/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.
 | 
| +
 | 
| +'''The <structure> element.
 | 
| +'''
 | 
| +
 | 
| +import os
 | 
| +
 | 
| +from grit.node import base
 | 
| +from grit.node import variant
 | 
| +
 | 
| +from grit import constants
 | 
| +from grit import exception
 | 
| +from grit import util
 | 
| +
 | 
| +import grit.gather.rc
 | 
| +import grit.gather.tr_html
 | 
| +import grit.gather.admin_template
 | 
| +import grit.gather.txt
 | 
| +import grit.gather.muppet_strings
 | 
| +import grit.gather.policy_json
 | 
| +
 | 
| +import grit.format.rc
 | 
| +import grit.format.rc_header
 | 
| +
 | 
| +# RTL languages
 | 
| +# TODO(jennyz): remove this fixed set of RTL language array
 | 
| +# when generic expand_variable code is added by grit team.
 | 
| +_RTL_LANGS = [
 | 
| +  'ar',
 | 
| +  'iw',
 | 
| +  'ur',
 | 
| +]
 | 
| +
 | 
| +# Type of the gatherer to use for each type attribute
 | 
| +_GATHERERS = {
 | 
| +  'accelerators' : grit.gather.rc.Accelerators,
 | 
| +  'admin_template' : grit.gather.admin_template.AdmGatherer,
 | 
| +  'dialog'  : grit.gather.rc.Dialog,
 | 
| +  'menu'    : grit.gather.rc.Menu,
 | 
| +  'muppet'  : grit.gather.muppet_strings.MuppetStrings,
 | 
| +  'rcdata'  : grit.gather.rc.RCData,
 | 
| +  'tr_html' : grit.gather.tr_html.TrHtml,
 | 
| +  'txt'     : grit.gather.txt.TxtFile,
 | 
| +  'version' : grit.gather.rc.Version,
 | 
| +  'policy_template_metafile' : grit.gather.policy_json.PolicyJson,
 | 
| +}
 | 
| +
 | 
| +
 | 
| +# Formatter instance to use for each type attribute
 | 
| +# when formatting .rc files.
 | 
| +_RC_FORMATTERS = {
 | 
| +  'accelerators' : grit.format.rc.RcSection(),
 | 
| +  'admin_template' : grit.format.rc.RcInclude('ADM'),
 | 
| +  'dialog'  : grit.format.rc.RcSection(),
 | 
| +  'menu'    : grit.format.rc.RcSection(),
 | 
| +  'muppet'  : grit.format.rc.RcInclude('XML'),
 | 
| +  'rcdata'  : grit.format.rc.RcSection(),
 | 
| +  'tr_html' : grit.format.rc.RcInclude('HTML'),
 | 
| +  'txt'     : grit.format.rc.RcInclude('TXT'),
 | 
| +  'version' : grit.format.rc.RcSection(),
 | 
| +  'policy_template_metafile': None,
 | 
| +}
 | 
| +
 | 
| +
 | 
| +# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
 | 
| +# that a skeleton variant is older than the original file.
 | 
| +
 | 
| +
 | 
| +class StructureNode(base.Node):
 | 
| +  '''A <structure> element.'''
 | 
| +
 | 
| +  def __init__(self):
 | 
| +    base.Node.__init__(self)
 | 
| +    self.gatherer = None
 | 
| +    self.skeletons = {}  # expressions to skeleton gatherers
 | 
| +
 | 
| +  def _IsValidChild(self, child):
 | 
| +    return isinstance(child, variant.SkeletonNode)
 | 
| +
 | 
| +  def MandatoryAttributes(self):
 | 
| +    return ['type', 'name', 'file']
 | 
| +
 | 
| +  def DefaultAttributes(self):
 | 
| +    return { 'encoding' : 'cp1252',
 | 
| +             'exclude_from_rc' : 'false',
 | 
| +             'line_end' : 'unix',
 | 
| +             'output_encoding' : 'utf-8',
 | 
| +             'generateid': 'true',
 | 
| +             'expand_variables' : 'false',
 | 
| +             'output_filename' : '',
 | 
| +             # TODO(joi) this is a hack - should output all generated files
 | 
| +             # as SCons dependencies; however, for now there is a bug I can't
 | 
| +             # find where GRIT doesn't build the matching fileset, therefore
 | 
| +             # this hack so that only the files you really need are marked as
 | 
| +             # dependencies.
 | 
| +             'sconsdep' : 'false',
 | 
| +             }
 | 
| +
 | 
| +  def IsExcludedFromRc(self):
 | 
| +    return self.attrs['exclude_from_rc'] == 'true'
 | 
| +
 | 
| +  def GetLineEnd(self):
 | 
| +    '''Returns the end-of-line character or characters for files output because
 | 
| +    of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
 | 
| +    '''
 | 
| +    if self.attrs['line_end'] == 'unix':
 | 
| +      return '\n'
 | 
| +    elif self.attrs['line_end'] == 'windows':
 | 
| +      return '\r\n'
 | 
| +    elif self.attrs['line_end'] == 'mac':
 | 
| +      return '\r'
 | 
| +    else:
 | 
| +      raise exception.UnexpectedAttribute(
 | 
| +        "Attribute 'line_end' must be one of 'linux' (default), 'windows' or 'mac'")
 | 
| +
 | 
| +  def GetCliques(self):
 | 
| +    if self.gatherer:
 | 
| +      return self.gatherer.GetCliques()
 | 
| +    else:
 | 
| +      return []
 | 
| +
 | 
| +  def GetTextualIds(self):
 | 
| +    if self.gatherer and self.attrs['type'] not in ['tr_html', 'admin_template', 'txt']:
 | 
| +      return self.gatherer.GetTextualIds()
 | 
| +    else:
 | 
| +      return [self.attrs['name']]
 | 
| +
 | 
| +  def ItemFormatter(self, t):
 | 
| +    if t == 'rc_header':
 | 
| +      return grit.format.rc_header.Item()
 | 
| +    elif (t in ['rc_all', 'rc_translateable', 'rc_nontranslateable'] and
 | 
| +          self.SatisfiesOutputCondition()):
 | 
| +      return _RC_FORMATTERS[self.attrs['type']]
 | 
| +    else:
 | 
| +      return super(type(self), self).ItemFormatter(t)
 | 
| +
 | 
| +  def RunGatherers(self, recursive=False, debug=False):
 | 
| +    if self.gatherer:
 | 
| +      return  # idempotent
 | 
| +
 | 
| +    gathertype = _GATHERERS[self.attrs['type']]
 | 
| +
 | 
| +    if debug:
 | 
| +      print 'Running gatherer %s for file %s' % (str(gathertype), self.FilenameToOpen())
 | 
| +
 | 
| +    self.gatherer = gathertype.FromFile(self.FilenameToOpen(),
 | 
| +                                        self.attrs['name'],
 | 
| +                                        self.attrs['encoding'])
 | 
| +    self.gatherer.SetUberClique(self.UberClique())
 | 
| +    self.gatherer.Parse()
 | 
| +
 | 
| +    for child in self.children:
 | 
| +      assert isinstance(child, variant.SkeletonNode)
 | 
| +      skel = gathertype.FromFile(child.FilenameToOpen(),
 | 
| +                                 self.attrs['name'],
 | 
| +                                 child.GetEncodingToUse())
 | 
| +      skel.SetUberClique(self.UberClique())
 | 
| +      skel.SetSkeleton(True)
 | 
| +      skel.Parse()
 | 
| +      self.skeletons[child.attrs['expr']] = skel
 | 
| +
 | 
| +  def GetSkeletonGatherer(self):
 | 
| +    '''Returns the gatherer for the alternate skeleton that should be used,
 | 
| +    based on the expressions for selecting skeletons, or None if the skeleton
 | 
| +    from the English version of the structure should be used.
 | 
| +    '''
 | 
| +    for expr in self.skeletons:
 | 
| +      if self.EvaluateCondition(expr):
 | 
| +        return self.skeletons[expr]
 | 
| +    return None
 | 
| +
 | 
| +  def GetFilePath(self):
 | 
| +    return self.ToRealPath(self.attrs['file'])
 | 
| +
 | 
| +  def HasFileForLanguage(self):
 | 
| +    return self.attrs['type'] in ['tr_html', 'admin_template', 'txt', 'muppet']
 | 
| +
 | 
| +  def FileForLanguage(self, lang, output_dir, create_file=True,
 | 
| +                      return_if_not_generated=True):
 | 
| +    '''Returns the filename of the file associated with this structure,
 | 
| +    for the specified language.
 | 
| +
 | 
| +    Args:
 | 
| +      lang: 'fr'
 | 
| +      output_dir: 'c:\temp'
 | 
| +      create_file: True
 | 
| +    '''
 | 
| +    assert self.HasFileForLanguage()
 | 
| +    if (lang == self.GetRoot().GetSourceLanguage() and
 | 
| +        self.attrs['expand_variables'] != 'true'):
 | 
| +      if return_if_not_generated:
 | 
| +        return self.GetFilePath()
 | 
| +      else:
 | 
| +        return None
 | 
| +    else:
 | 
| +      if self.attrs['output_filename'] != '':
 | 
| +        filename = self.attrs['output_filename']
 | 
| +      else:
 | 
| +        filename = os.path.basename(self.attrs['file'])
 | 
| +      assert len(filename)
 | 
| +      filename = '%s_%s' % (lang, filename)
 | 
| +      filename = os.path.join(output_dir, filename)
 | 
| +
 | 
| +      if create_file:
 | 
| +        text = self.gatherer.Translate(
 | 
| +          lang,
 | 
| +          pseudo_if_not_available=self.PseudoIsAllowed(),
 | 
| +          fallback_to_english=self.ShouldFallbackToEnglish(),
 | 
| +          skeleton_gatherer=self.GetSkeletonGatherer())
 | 
| +
 | 
| +        file_object = util.WrapOutputStream(file(filename, 'wb'),
 | 
| +                                            self._GetOutputEncoding())
 | 
| +        file_contents = util.FixLineEnd(text, self.GetLineEnd())
 | 
| +        if self.attrs['expand_variables'] == 'true':
 | 
| +          file_contents = file_contents.replace('[GRITLANGCODE]', lang)
 | 
| +          # TODO(jennyz): remove this hard coded logic for expanding
 | 
| +          # [GRITDIR] variable for RTL languages when the generic
 | 
| +          # expand_variable code is added by grit team.
 | 
| +          if lang in _RTL_LANGS :
 | 
| +            file_contents = file_contents.replace('[GRITDIR]', 'dir="RTL"')
 | 
| +          else :
 | 
| +            file_contents = file_contents.replace('[GRITDIR]', 'dir="LTR"')
 | 
| +        if self._ShouldAddBom():
 | 
| +          file_object.write(constants.BOM)
 | 
| +        file_object.write(file_contents)
 | 
| +        file_object.close()
 | 
| +
 | 
| +      return filename
 | 
| +
 | 
| +  def _GetOutputEncoding(self):
 | 
| +    '''Python doesn't natively support UTF encodings with a BOM signature,
 | 
| +    so we add support by allowing you to append '-sig' to the encoding name.
 | 
| +    This function returns the specified output encoding minus that part.
 | 
| +    '''
 | 
| +    enc = self.attrs['output_encoding']
 | 
| +    if enc.endswith('-sig'):
 | 
| +      return enc[0:len(enc) - len('-sig')]
 | 
| +    else:
 | 
| +      return enc
 | 
| +
 | 
| +  def _ShouldAddBom(self):
 | 
| +    '''Returns true if output files should have the Unicode BOM prepended.
 | 
| +    '''
 | 
| +    return self.attrs['output_encoding'].endswith('-sig')
 | 
| +
 | 
| +  # static method
 | 
| +  def Construct(parent, name, type, file, encoding='cp1252'):
 | 
| +    '''Creates a new node which is a child of 'parent', with attributes set
 | 
| +    by parameters of the same name.
 | 
| +    '''
 | 
| +    node = StructureNode()
 | 
| +    node.StartParsing('structure', parent)
 | 
| +    node.HandleAttribute('name', name)
 | 
| +    node.HandleAttribute('type', type)
 | 
| +    node.HandleAttribute('file', file)
 | 
| +    node.HandleAttribute('encoding', encoding)
 | 
| +    node.EndParsing()
 | 
| +    return node
 | 
| +  Construct = staticmethod(Construct)
 | 
| +
 | 
| 
 | 
| Property changes on: grit/node/structure.py
 | 
| ___________________________________________________________________
 | 
| Added: svn:eol-style
 | 
|    + LF
 | 
| 
 | 
| 
 |