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