PageRenderTime 1ms CodeModel.GetById 29ms app.highlight 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/grit/grit/node/structure.py

https://github.com/akesling/chromium
Python | 260 lines | 220 code | 20 blank | 20 comment | 1 complexity | 7407ec6bed89bcc9f91e1831340e1822 MD5 | raw file
  1#!/usr/bin/python2.4
  2# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
  3# Use of this source code is governed by a BSD-style license that can be
  4# found in the LICENSE file.
  5
  6'''The <structure> element.
  7'''
  8
  9import os
 10
 11from grit.node import base
 12from grit.node import variant
 13
 14from grit import constants
 15from grit import exception
 16from grit import util
 17
 18import grit.gather.rc
 19import grit.gather.tr_html
 20import grit.gather.admin_template
 21import grit.gather.txt
 22import grit.gather.muppet_strings
 23
 24import grit.format.rc
 25import grit.format.rc_header
 26
 27# RTL languages
 28# TODO(jennyz): remove this fixed set of RTL language array
 29# when generic expand_variable code is added by grit team.
 30_RTL_LANGS = [
 31  'ar',
 32  'iw',
 33  'ur',
 34]
 35
 36# Type of the gatherer to use for each type attribute
 37_GATHERERS = {
 38  'accelerators' : grit.gather.rc.Accelerators,
 39  'admin_template' : grit.gather.admin_template.AdmGatherer,
 40  'dialog'  : grit.gather.rc.Dialog,
 41  'menu'    : grit.gather.rc.Menu,
 42  'muppet'  : grit.gather.muppet_strings.MuppetStrings,
 43  'rcdata'  : grit.gather.rc.RCData,
 44  'tr_html' : grit.gather.tr_html.TrHtml,
 45  'txt'     : grit.gather.txt.TxtFile,
 46  'version' : grit.gather.rc.Version,
 47}
 48
 49
 50# Formatter instance to use for each type attribute
 51# when formatting .rc files.
 52_RC_FORMATTERS = {
 53  'accelerators' : grit.format.rc.RcSection(),
 54  'admin_template' : grit.format.rc.RcInclude('ADM'),
 55  'dialog'  : grit.format.rc.RcSection(),
 56  'menu'    : grit.format.rc.RcSection(),
 57  'muppet'  : grit.format.rc.RcInclude('XML'),
 58  'rcdata'  : grit.format.rc.RcSection(),
 59  'tr_html' : grit.format.rc.RcInclude('HTML'),
 60  'txt'     : grit.format.rc.RcInclude('TXT'),
 61  'version' : grit.format.rc.RcSection(),
 62}
 63
 64
 65# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
 66# that a skeleton variant is older than the original file.
 67
 68
 69class StructureNode(base.Node):
 70  '''A <structure> element.'''
 71
 72  def __init__(self):
 73    base.Node.__init__(self)
 74    self.gatherer = None
 75    self.skeletons = {}  # expressions to skeleton gatherers
 76
 77  def _IsValidChild(self, child):
 78    return isinstance(child, variant.SkeletonNode)
 79
 80  def MandatoryAttributes(self):
 81    return ['type', 'name', 'file']
 82
 83  def DefaultAttributes(self):
 84    return { 'encoding' : 'cp1252',
 85             'exclude_from_rc' : 'false',
 86             'line_end' : 'unix',
 87             'output_encoding' : 'utf-8',
 88             'generateid': 'true',
 89             'expand_variables' : 'false',
 90             'output_filename' : '',
 91             # TODO(joi) this is a hack - should output all generated files
 92             # as SCons dependencies; however, for now there is a bug I can't
 93             # find where GRIT doesn't build the matching fileset, therefore
 94             # this hack so that only the files you really need are marked as
 95             # dependencies.
 96             'sconsdep' : 'false',
 97             }
 98
 99  def IsExcludedFromRc(self):
100    return self.attrs['exclude_from_rc'] == 'true'
101
102  def GetLineEnd(self):
103    '''Returns the end-of-line character or characters for files output because
104    of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
105    '''
106    if self.attrs['line_end'] == 'unix':
107      return '\n'
108    elif self.attrs['line_end'] == 'windows':
109      return '\r\n'
110    elif self.attrs['line_end'] == 'mac':
111      return '\r'
112    else:
113      raise exception.UnexpectedAttribute(
114        "Attribute 'line_end' must be one of 'linux' (default), 'windows' or 'mac'")
115
116  def GetCliques(self):
117    if self.gatherer:
118      return self.gatherer.GetCliques()
119    else:
120      return []
121
122  def GetTextualIds(self):
123    if self.gatherer and self.attrs['type'] not in ['tr_html', 'admin_template', 'txt']:
124      return self.gatherer.GetTextualIds()
125    else:
126      return [self.attrs['name']]
127
128  def ItemFormatter(self, t):
129    if t == 'rc_header':
130      return grit.format.rc_header.Item()
131    elif (t in ['rc_all', 'rc_translateable', 'rc_nontranslateable'] and
132          self.SatisfiesOutputCondition()):
133      return _RC_FORMATTERS[self.attrs['type']]
134    else:
135      return super(type(self), self).ItemFormatter(t)
136
137  def RunGatherers(self, recursive=False, debug=False):
138    if self.gatherer:
139      return  # idempotent
140
141    gathertype = _GATHERERS[self.attrs['type']]
142
143    if debug:
144      print 'Running gatherer %s for file %s' % (str(gathertype), self.FilenameToOpen())
145
146    self.gatherer = gathertype.FromFile(self.FilenameToOpen(),
147                                        self.attrs['name'],
148                                        self.attrs['encoding'])
149    self.gatherer.SetUberClique(self.UberClique())
150    self.gatherer.Parse()
151
152    for child in self.children:
153      assert isinstance(child, variant.SkeletonNode)
154      skel = gathertype.FromFile(child.FilenameToOpen(),
155                                 self.attrs['name'],
156                                 child.GetEncodingToUse())
157      skel.SetUberClique(self.UberClique())
158      skel.SetSkeleton(True)
159      skel.Parse()
160      self.skeletons[child.attrs['expr']] = skel
161
162  def GetSkeletonGatherer(self):
163    '''Returns the gatherer for the alternate skeleton that should be used,
164    based on the expressions for selecting skeletons, or None if the skeleton
165    from the English version of the structure should be used.
166    '''
167    for expr in self.skeletons:
168      if self.EvaluateCondition(expr):
169        return self.skeletons[expr]
170    return None
171
172  def GetFilePath(self):
173    return self.ToRealPath(self.attrs['file'])
174
175  def HasFileForLanguage(self):
176    return self.attrs['type'] in ['tr_html', 'admin_template', 'txt', 'muppet']
177
178  def FileForLanguage(self, lang, output_dir, create_file=True,
179                      return_if_not_generated=True):
180    '''Returns the filename of the file associated with this structure,
181    for the specified language.
182
183    Args:
184      lang: 'fr'
185      output_dir: 'c:\temp'
186      create_file: True
187    '''
188    assert self.HasFileForLanguage()
189    if (lang == self.GetRoot().GetSourceLanguage() and
190        self.attrs['expand_variables'] != 'true'):
191      if return_if_not_generated:
192        return self.GetFilePath()
193      else:
194        return None
195    else:
196      if self.attrs['output_filename'] != '':
197        filename = self.attrs['output_filename']
198      else:
199        filename = os.path.basename(self.attrs['file'])
200      assert len(filename)
201      filename = '%s_%s' % (lang, filename)
202      filename = os.path.join(output_dir, filename)
203
204      if create_file:
205        text = self.gatherer.Translate(
206          lang,
207          pseudo_if_not_available=self.PseudoIsAllowed(),
208          fallback_to_english=self.ShouldFallbackToEnglish(),
209          skeleton_gatherer=self.GetSkeletonGatherer())
210
211        file_object = util.WrapOutputStream(file(filename, 'wb'),
212                                            self._GetOutputEncoding())
213        file_contents = util.FixLineEnd(text, self.GetLineEnd())
214        if self.attrs['expand_variables'] == 'true':
215          file_contents = file_contents.replace('[GRITLANGCODE]', lang)
216          # TODO(jennyz): remove this hard coded logic for expanding
217          # [GRITDIR] variable for RTL languages when the generic
218          # expand_variable code is added by grit team.
219          if lang in _RTL_LANGS :
220            file_contents = file_contents.replace('[GRITDIR]', 'dir="RTL"')
221          else :
222            file_contents = file_contents.replace('[GRITDIR]', 'dir="LTR"')
223        if self._ShouldAddBom():
224          file_object.write(constants.BOM)
225        file_object.write(file_contents)
226        file_object.close()
227
228      return filename
229
230  def _GetOutputEncoding(self):
231    '''Python doesn't natively support UTF encodings with a BOM signature,
232    so we add support by allowing you to append '-sig' to the encoding name.
233    This function returns the specified output encoding minus that part.
234    '''
235    enc = self.attrs['output_encoding']
236    if enc.endswith('-sig'):
237      return enc[0:len(enc) - len('-sig')]
238    else:
239      return enc
240
241  def _ShouldAddBom(self):
242    '''Returns true if output files should have the Unicode BOM prepended.
243    '''
244    return self.attrs['output_encoding'].endswith('-sig')
245
246  # static method
247  def Construct(parent, name, type, file, encoding='cp1252'):
248    '''Creates a new node which is a child of 'parent', with attributes set
249    by parameters of the same name.
250    '''
251    node = StructureNode()
252    node.StartParsing('structure', parent)
253    node.HandleAttribute('name', name)
254    node.HandleAttribute('type', type)
255    node.HandleAttribute('file', file)
256    node.HandleAttribute('encoding', encoding)
257    node.EndParsing()
258    return node
259  Construct = staticmethod(Construct)
260