/tools/grit/grit/node/misc.py
Python | 272 lines | 237 code | 17 blank | 18 comment | 18 complexity | 890b05e5a95adb751cb74d28644bc57e 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'''Miscellaneous node types. 7''' 8 9import os.path 10 11from grit.node import base 12from grit.node import message 13 14from grit import exception 15from grit import constants 16from grit import util 17 18import grit.format.rc_header 19 20 21 22class IfNode(base.Node): 23 '''A node for conditional inclusion of resources. 24 ''' 25 26 def _IsValidChild(self, child): 27 from grit.node import empty 28 assert self.parent, '<if> node should never be root.' 29 if isinstance(self.parent, empty.IncludesNode): 30 from grit.node import include 31 return isinstance(child, include.IncludeNode) 32 elif isinstance(self.parent, empty.MessagesNode): 33 from grit.node import message 34 return isinstance(child, message.MessageNode) 35 elif isinstance(self.parent, empty.StructuresNode): 36 from grit.node import structure 37 return isinstance(child, structure.StructureNode) 38 else: 39 return False 40 41 def MandatoryAttributes(self): 42 return ['expr'] 43 44 def IsConditionSatisfied(self): 45 '''Returns true if and only if the Python expression stored in attribute 46 'expr' evaluates to true. 47 ''' 48 return self.EvaluateCondition(self.attrs['expr']) 49 50 51class ReleaseNode(base.Node): 52 '''The <release> element.''' 53 54 def _IsValidChild(self, child): 55 from grit.node import empty 56 return isinstance(child, (empty.IncludesNode, empty.MessagesNode, 57 empty.StructuresNode, empty.IdentifiersNode)) 58 59 def _IsValidAttribute(self, name, value): 60 return ( 61 (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or 62 name == 'allow_pseudo' 63 ) 64 65 def MandatoryAttributes(self): 66 return ['seq'] 67 68 def DefaultAttributes(self): 69 return { 'allow_pseudo' : 'true' } 70 71 def GetReleaseNumber(): 72 '''Returns the sequence number of this release.''' 73 return self.attribs['seq'] 74 75 def ItemFormatter(self, t): 76 if t == 'data_package': 77 from grit.format import data_pack 78 return data_pack.DataPack() 79 else: 80 return super(type(self), self).ItemFormatter(t) 81 82class GritNode(base.Node): 83 '''The <grit> root element.''' 84 85 def __init__(self): 86 base.Node.__init__(self) 87 self.output_language = '' 88 self.defines = {} 89 90 def _IsValidChild(self, child): 91 from grit.node import empty 92 return isinstance(child, (ReleaseNode, empty.TranslationsNode, 93 empty.OutputsNode)) 94 95 def _IsValidAttribute(self, name, value): 96 if name not in ['base_dir', 'source_lang_id', 97 'latest_public_release', 'current_release', 98 'enc_check', 'tc_project']: 99 return False 100 if name in ['latest_public_release', 'current_release'] and value.strip( 101 '0123456789') != '': 102 return False 103 return True 104 105 def MandatoryAttributes(self): 106 return ['latest_public_release', 'current_release'] 107 108 def DefaultAttributes(self): 109 return { 110 'base_dir' : '.', 111 'source_lang_id' : 'en', 112 'enc_check' : constants.ENCODING_CHECK, 113 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE', 114 } 115 116 def EndParsing(self): 117 base.Node.EndParsing(self) 118 if (int(self.attrs['latest_public_release']) 119 > int(self.attrs['current_release'])): 120 raise exception.Parsing('latest_public_release cannot have a greater ' 121 'value than current_release') 122 123 self.ValidateUniqueIds() 124 125 # Add the encoding check if it's not present (should ensure that it's always 126 # present in all .grd files generated by GRIT). If it's present, assert if 127 # it's not correct. 128 if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '': 129 self.attrs['enc_check'] = constants.ENCODING_CHECK 130 else: 131 assert self.attrs['enc_check'] == constants.ENCODING_CHECK, ( 132 'Are you sure your .grd file is in the correct encoding (UTF-8)?') 133 134 def ValidateUniqueIds(self): 135 '''Validate that 'name' attribute is unique in all nodes in this tree 136 except for nodes that are children of <if> nodes. 137 ''' 138 unique_names = {} 139 duplicate_names = [] 140 for node in self: 141 if isinstance(node, message.PhNode): 142 continue # PhNode objects have a 'name' attribute which is not an ID 143 144 node_ids = node.GetTextualIds() 145 if node_ids: 146 for node_id in node_ids: 147 if util.SYSTEM_IDENTIFIERS.match(node_id): 148 continue # predefined IDs are sometimes used more than once 149 150 # Don't complain about duplicate IDs if they occur in a node that is 151 # inside an <if> node. 152 if (node_id in unique_names and node_id not in duplicate_names and 153 (not node.parent or not isinstance(node.parent, IfNode))): 154 duplicate_names.append(node_id) 155 unique_names[node_id] = 1 156 157 if len(duplicate_names): 158 raise exception.DuplicateKey(', '.join(duplicate_names)) 159 160 161 def GetCurrentRelease(self): 162 '''Returns the current release number.''' 163 return int(self.attrs['current_release']) 164 165 def GetLatestPublicRelease(self): 166 '''Returns the latest public release number.''' 167 return int(self.attrs['latest_public_release']) 168 169 def GetSourceLanguage(self): 170 '''Returns the language code of the source language.''' 171 return self.attrs['source_lang_id'] 172 173 def GetTcProject(self): 174 '''Returns the name of this project in the TranslationConsole, or 175 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined.''' 176 return self.attrs['tc_project'] 177 178 def SetOwnDir(self, dir): 179 '''Informs the 'grit' element of the directory the file it is in resides. 180 This allows it to calculate relative paths from the input file, which is 181 what we desire (rather than from the current path). 182 183 Args: 184 dir: r'c:\bla' 185 186 Return: 187 None 188 ''' 189 assert dir 190 self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir'])) 191 192 def GetBaseDir(self): 193 '''Returns the base directory, relative to the working directory. To get 194 the base directory as set in the .grd file, use GetOriginalBaseDir() 195 ''' 196 if hasattr(self, 'base_dir'): 197 return self.base_dir 198 else: 199 return self.GetOriginalBaseDir() 200 201 def GetOriginalBaseDir(self): 202 '''Returns the base directory, as set in the .grd file. 203 ''' 204 return self.attrs['base_dir'] 205 206 def GetOutputFiles(self): 207 '''Returns the list of <file> nodes that are children of this node's 208 <outputs> child.''' 209 for child in self.children: 210 if child.name == 'outputs': 211 return child.children 212 raise exception.MissingElement() 213 214 def ItemFormatter(self, t): 215 if t == 'rc_header': 216 from grit.format import rc_header # import here to avoid circular dep 217 return rc_header.TopLevel() 218 elif t in ['rc_all', 'rc_translateable', 'rc_nontranslateable']: 219 from grit.format import rc # avoid circular dep 220 return rc.TopLevel() 221 elif t == 'resource_map_header': 222 from grit.format import resource_map 223 return resource_map.HeaderTopLevel() 224 elif t == 'resource_map_source': 225 from grit.format import resource_map 226 return resource_map.SourceTopLevel() 227 else: 228 return super(type(self), self).ItemFormatter(t) 229 230 def SetOutputContext(self, output_language, defines): 231 self.output_language = output_language 232 self.defines = defines 233 234 235class IdentifierNode(base.Node): 236 '''A node for specifying identifiers that should appear in the resource 237 header file, and be unique amongst all other resource identifiers, but don't 238 have any other attributes or reference any resources. 239 ''' 240 241 def MandatoryAttributes(self): 242 return ['name'] 243 244 def DefaultAttributes(self): 245 return { 'comment' : '', 'id' : '' } 246 247 def ItemFormatter(self, t): 248 if t == 'rc_header': 249 return grit.format.rc_header.Item() 250 251 def GetId(self): 252 '''Returns the id of this identifier if it has one, None otherwise 253 ''' 254 if 'id' in self.attrs: 255 return self.attrs['id'] 256 return None 257 258 # static method 259 def Construct(parent, name, id, comment): 260 '''Creates a new node which is a child of 'parent', with attributes set 261 by parameters of the same name. 262 ''' 263 node = IdentifierNode() 264 node.StartParsing('identifier', parent) 265 node.HandleAttribute('name', name) 266 node.HandleAttribute('id', id) 267 node.HandleAttribute('comment', comment) 268 node.EndParsing() 269 return node 270 Construct = staticmethod(Construct) 271 272